7

重複の可能性:
インスタンス初期化子とコンストラクターの違いは?

必要なすべての作業をコンストラクター内で実行できるのに、なぜ Java で非静的ブロックが必要なのですか?

編集:非静的ブロックがコンストラクターの前に毎回実行される通常のクラスはどうですか?

4

2 に答える 2

14

@Bohemianの回答に加えて。

複数のコンストラクターがある場合、初期化ブロックは重複を避けます。

public class A {
     final Map<String, String> map = new HashMap<String, String>(); {
        // put things in map.
     }
     final int number; {
        int number;
        try {
            number = throwsAnException();
        } catch (Exception e) {
            number = 5;
        }
        this.number = number;
     }

     public A() { /* constructor 1 */ }
     public A(int i) { /* constructor 2 */ }
}

非静的ブロックがコンストラクターの前に毎回実行される通常のクラスはどうですか?

技術的な順番は

  • スーパーコンストラクターは常に最初に呼び出されます
  • 出現順にすべての初期化ブロック。
  • コンストラクターコード

実際には、このコードはすべて各コンストラクターのバイト コード内にあるため、実行時にコンストラクターの前後には何もありません。


初期化の順序についてこれ以上混乱する前に

public class Main extends SuperClass {
    {
        System.out.println("Initialiser block before constructor");
    }

    Main() {
        System.out.println("Main constructor");
    }

    {
        System.out.println("Initialiser block after constructor");

    }

    public static void main(String... args) {
        new Main() {{
            System.out.println("Anonymous initalizer block");
        }};
    }
}

class SuperClass {
    SuperClass() {
        System.out.println("SuperClass constructor");
    }
}

版画

SuperClass constructor
Initialiser block before constructor
Initialiser block after constructor
Main constructor
Anonymous initalizer block
于 2012-08-08T17:36:32.003 に答える
8

匿名クラスで使用できます。

new MyClass() {
    {
         // do something extra on construction (after the constructor executes)
    }
}

これは、「ルックアップ」マップ (固定コンテンツ) を適切に初期化するのに特に便利です。

Map<String, String> map = new HashMap<String, String>() {
    {
        put("foo", "bar");
        put("one", "two");
        // etc
    }
};

参考までに、これは「二重ブレースの初期化」と呼ばれることがありますが、実際には単に初期化ブロックを使用しているだけです。

このような匿名クラスは技術的にはサブクラスですが、変更不可能なマップを作成する際にこの手法を使用する従来の手法と比較すると、この利点が示されます。

データと割り当てを一緒に配置する、この単純なワンライナーを比較してください。

private static final Map<String, String> map = Collections.unmodifiableMap(
    new HashMap<String, String>() {{
        put("foo", "bar");
        put("one", "two");
        // etc
    }});

この混乱では、final割り当てが 1 つしか許可されていないため、別のオブジェクトを作成する必要があります。

private static final Map<String, String> map;

static {
    Map<String, String> tempMap = new HashMap<String, String>();
    tempMap.put("foo", "bar");
    tempMap.put("one", "two");
    // etc
    map = Collections.unmodifiableMap(tempMap);
}

また、message バージョンでは、2 つのステートメントが隣接している必要がないため、変更不可能なマップの内容がわかりにくくなる可能性があることに注意してください。

于 2012-08-08T17:30:45.860 に答える