インタビューの準備として、私は記憶をリフレッシュし、Java言語のトリッキーであまり知られていないニュアンスを実際に探すことにしました。 私の意見では、最も興味深い5つのポイントを選択できます。
記事の2番目の部分はすでに到着しています。
1.非静的初期化ブロック。Javaには静的初期化ブロック(
クラス初期化子 )があり、そのコードはクラスが最初にロードされたときに実行されることは誰もが知っていると思います。
class Foo { static List<Character> abc; static { abc = new LinkedList<Character>(); for (char c = 'A'; c <= 'Z'; ++c) { abc.add( c ); } } }
しかし、非静的
インスタンス初期化子もあり
ます 。 これらは、どのコンストラクターが呼び出されたかに関係なく、オブジェクトを初期化するか、たとえばログに記録することができます。
class Bar { { System.out.println("Bar: "); } }
この初期化メソッドは、コンストラクターが持つことのできない匿名内部クラスに非常に役立ちます。 さらに、Javaの構文を制限するにもかかわらず、それらを使用して、コレクションをエレガントに初期化できます。
Map<String, String> map = new HashMap<String, String>() {{ put("", ""); put("", ""); put("", ""); }};
非常に強力なツールですね。
JFrame frame = new JFrame() {{ add(new JPanel() {{ add(new JLabel("?") {{ setBackground(Color.BLACK); setForeground(Color.WHITE); }}); add(new JButton("!") {{ addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { System.out.println(" - !"); } }); }}); }}); }};
カットの下の残りの4つのポイント。
2.インターフェイスのネストされたクラス。インターフェイスに
ネストされたクラスは、これらの修飾子を明示的に指定しなくても、
パブリックで静的です。 インターフェース内にクラスを配置することにより、このインターフェースのAPIの不可欠な部分であり、他の場所では使用されないことを示します。
interface Colorable { public Color getColor(); public static class Color { private int red, green, blue; Color(int red, int green, int blue) { this.red = red; this.green = green; this.blue = blue; } int getRed() { return red; } int getGreen() { return green; } int getBlue() { return blue; } } } class Triangle implements Colorable { private Color color;
このようなクラスは静的なので、囲んでいるクラスのオブジェクトを参照せずにインスタンス化できますが、外部インターフェイスまたはそれを実装するクラスのタイプのみを指定します。
Colorable.Color color = new Colorable.Color(0, 0, 0); color = new Triangle.Color(255, 255, 255);
このイディオムの最も有名な例はおそらく、連想辞書のキーと値のペアを含むMap.Entry <K、V>クラスです。
3.返される型の共変。Java SE 5以降、メソッドからの戻り値の型は共変です。 これは、
オーバーライドされたメソッドでは、オーバーラップしたメソッドの結果サブタイプを結果タイプとして使用できることを意味し
ます 。
class Covariance implements Cloneable { @Override public Covariance clone() { Object cloned = null; try { cloned = super.clone(); } catch (CloneNotSupportedException exc) {
Object.clone()メソッドには次のシグネチャがあります。
protected Object clone()
戻り値の型がオブジェクトから共分散に変更されていることに注意してください。 これで、たとえば、以前のバージョンのJDKで必要だったclone()メソッドの結果を有効なオブジェクト型にキャストする必要がなくなりました。 このコードの代わりに:
Covariance foo = new Covariance(); Covariance bar = (Covariance)foo.clone();
次のコードを安全に記述できます。
Covariance foo = new Covariance(); Covariance bar = foo.clone();
4.オペレーターのブロックを終了します。gotoは予約済みのJavaキーワードですが、プログラムで使用することはできません。 さようなら? 現在のサイクルだけでなく、ラベルで示されるフレーミングサイクルも(それぞれ)中断および継続することができる
breakおよび
continue演算子に置き換えられました。
String a = "quadratic", b = "complexity"; boolean hasSame = false; outer: for (int i = 0; i < a.length(); ++i) { for (int j = 0; j < b.length(); ++j) { if (a.charAt(i) == b.charAt(j)) { hasSame = true; break outer; } } } System.out.println(hasSame);
しかし、多くの人は、Javaでは
breakステートメントでループを中断できるだけでなく、ステートメントのブロックを完全に残すこともできることに気づいていません。
gotoオペレーターが一方通行でないのはなぜですか? 彼らが言うように、一歩ではなく前進する。
long factorial(int n) { long result = 1; scope: { if (n == 0) { break scope; } result = n * factorial(n - 1); } return result; }
このようなジャンプの実際的な価値は非常に疑わしく、構造プログラミングの原則に違反していますが、この可能性について知る価値があると思います。
5.内部クラスからのデータの変更。最終的なキーワードはJavaで提供されますが、実際には、オブジェクトを指すのではなく、オブジェクト自体の不変性を指定する方法はありません(プリミティブには適用されません)。 原則として、ゲッターと純粋な関数のみを提供することで不変クラスを設計できますが、たとえば不変配列を作成することはできません。 これは、私には、言語の設計における重要な省略です。 ここでは、予約されているが禁止されている
constキーワードが役立ちます。 次のバージョンを楽しみにしていますか?
final int[] array = {1, 2, 3, 4, 5}; new Object() { void twice() { for (int i = 0; i < array.length; ++i) { array[i] *= 2; } } }.twice();
したがって、ファイナライズされたものの、実際には変更可能なデータは、それが配列であろうと他の非永続オブジェクトであろうと、
内部クラスのコンテキストからであっても変更できます。 残念ながら、プリミティブ型の文字列とラッパーでは、このトリックは機能しません。
最後のキーワードに
だまされないでください。
あなたが記事を好きなら- 継続するために ...