17

残念ながら、私は約 5 年間 Java のコーディングを行っていないため、次のコードがどのように、またはなぜ機能するのかまったく思い出せません。

私は同様の例に出くわし、これに分解しました。コメントの下の部分に重点が置かれています。コンストラクター表記の後に二重括弧で囲まれたブロックが続きません。残念ながら、Java のドキュメントや Google を使用しても何も見つかりません (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;
    }
}

だからここに私の質問があります:

  1. この表記法/構文はどのように呼ばれますか?
  2. それに関するドキュメントはどこで読めますか?

誰かが最初の質問に答えてくれれば、2 番目の質問に自分で答えられると思います。

明確にするために:出力がJohn Johnson;) であることは知っていますが、なぜそれが機能しているのかわかりません。

4

3 に答える 3

21

これは、二重ブレースの初期化として知られています。

最初の中括弧は新しい AnonymousInnerClass を作成し、2 番目の中括弧は匿名内部クラスがインスタンス化されるときに実行されるインスタンス初期化子ブロックを宣言します。このタイプのイニシャライザ ブロックは、クラスのインスタンス スコープ内で宣言されるため、正式には「インスタンス イニシャライザ」と呼ばれます。「静的イニシャライザ」は、キーワード static がブロックを開始するブレースの前に配置される関連概念です。これは、クラスローダがクラスのロードを完了するとすぐにクラス レベルで実行されます ( http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.6で指定)。) 初期化子ブロックは、包含スコープで使用可能な任意のメソッド、フィールド、および最終変数を使用できますが、初期化子がコンストラクターの前に実行されるという事実に注意する必要があります。

これは、匿名サブクラスを作成するため、非最終クラスに対してのみ機能します。

于 2009-07-08T19:39:59.500 に答える
16

コードのレイアウトを少し変えてみましょう。

MyTest tester = new MyTest() {
  {
    setName("John Johnson");
  }
};

ここに表示されるものは、二重ブレースの初期化と呼ばれます。class の匿名内部サブクラスとMyTest、オブジェクトの構築時に実行されるコードを含むブロックである初期化ブロックがあります。

通常、そのようなコードはコンストラクターに配置しますが、匿名の内部クラスはコンストラクターを持つことができないため、コードが想定どおりに実行されることを保証するには、これが唯一の方法です。

そうは言っても、これを行うのは少し醜いです。より良い方法があります。ただし、私は時々それを自分で使用します。通常は、次のイディオムで不変のマップを作成します。

final Map<String, Integer> textToInt = Collections.unmodifiableMap(new HashMap<String, Integer>() {{
    put("one", 1);
    put("two", 2);
    // etc
}});

これにより、新しいマップが作成され、オーバーライドされ、初期化ブロックでいくつかの値が追加され、変更不可能なマップにラップされます。

于 2009-07-08T19:40:36.503 に答える
-5
MyTest tester = new MyTest() {{
   setName("John Johnson");
}};

と同じです

MyTest tester = new MyTest();
tester.setName("John Johnson");
于 2009-07-08T20:00:29.677 に答える