次の二重中括弧を含むこのコンストラクター呼び出しは何ですか?
-
11-09-2019 - |
質問
残念ながら、私は Java をコーディングしたことが 5 年ほどないので、次のコードがどのように、なぜ機能するのかまったく思い出せません。
私は同様の例に遭遇し、これを分析しました。コメントの下の部分が強調されます。二重括弧内のブロックが後に続くコンストラクター表記がわかりません。そして残念ながら、Java ドキュメントや Google を使用しても何も見つかりません (どの単語をグーグルすればよいでしょうか?)。
package syntaxtest;
public class Main {
public static void main(String[] args) {
// What kind of notation is this?
MyTest tester = new MyTest() {{
setName("John Johnson");
}};
System.out.println(tester.getName());
}
}
class MyTest {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
そこで私の質問は次のとおりです。
- この表記/構文はどのように呼ばれますか?
- それに関するドキュメントはどこで読めますか?
誰かが最初の質問に対する答えを提供してくれれば、2 番目の質問に自分で答えられるようになると思います/願っています。
明確にするために:私は出力が John Johnson
;) しかし、なぜそれが機能するのかはわかりません。
解決
最初のブレースは、新たに作成し、 AnonymousInnerClass、第二 インスタンス初期化子ブロックを宣言 それが実行されたときに匿名の内部を クラスがインスタンス化されます。このタイプの 初期化子ブロックが正式に呼ばれています そのため、「インスタンス初期化子」、 インスタンスのスコープ内で宣言されます 「静的初期化子」 - クラスの どこ関連する概念です キーワードの静的を前に配置されます ブロックを開始ブレース、およびその すぐにクラスレベルで実行されます クラスローダは、ロードが完了すると で指定したクラス( http://java.sun.com/docs/books /jls/third_edition/html/classes.html#8.6する) 初期化子ブロックは、いずれかを使用することができます メソッド、フィールド、最終的な変数 含む範囲で利用できるが、 1は、その事実を警戒する必要があり 初期化子は、前に実行されています コンストラクタます。
唯一の非最終のためのこの唯一の作品 クラス、それが作成されますので、 匿名のサブクラスます。
他のヒント
のは、少し異なるコードをレイアウトしてみましょう。
MyTest tester = new MyTest() {
{
setName("John Johnson");
}
};
あなたがここで見ると、のダブルブレースの初期化のと呼ばれています。あなたは、オブジェクトが作成されたときに実行されるコードが含まれているブロックである初期化子ブロックとともに、クラスMyTest
の匿名内部サブクラスを持っています。
通常は、コンストラクタ内でこのようなコードを置くだろうが、匿名内部クラスはコンストラクタを持つことができないので、これは、それがになっていたときに、コードが実行される保証する唯一の方法である。
それがこれを行うには少し醜いだ、と述べました。より良い方法があります。しかし、私は不変のマップを作成するには、通常、次のイディオムで、時々それを自分自身を使用してください:
final Map<String, Integer> textToInt = Collections.unmodifiableMap(new HashMap<String, Integer>() {{
put("one", 1);
put("two", 2);
// etc
}});
新しいマップを作成する、それを上書きし、初期化子ブロックでそれにいくつかの値を追加し、変更不可能なマップでそれをラップします。
MyTest tester = new MyTest() {{
setName("John Johnson");
}};
と同一であります
MyTest tester = new MyTest();
tester.setName("John Johnson");