インスタンスイニシャライザ構文は、クラス内のメソッドやコンストラクタの外で、波括弧で囲まれた特別なコードブロックです。このブロックは instance initializer block と呼ばれます。新しいクラスのオブジェクトが作成されるたびに実行され、親クラスのコンストラクタが呼び出された後、現在のクラスのコンストラクタのコードが実行される前に実行されます。
public class Example { { // インスタンスイニシャライザブロック System.out.println("インスタンスの初期化"); } private int x; public Example(int x) { this.x = x; System.out.println("コンストラクタ"); } }
インスタンスイニシャライザは次の目的で有用です:
クラスにインスタンスイニシャライザとコンストラクタの両方が存在する場合、どのような順序で実行されますか?
回答: 最初にインスタンスイニシャライザが実行され、その後にコンストラクタのコードが実行されます。同じクラスに複数のインスタンスイニシャライザブロックがある場合、それらは記述された順序で実行されます。
例:
public class Demo { { System.out.println("インスタンスイニシャライザ 1"); } public Demo() { System.out.println("コンストラクタ"); } { System.out.println("インスタンスイニシャライザ 2"); } } // new Demo() の出力: // インスタンスイニシャライザ 1 // インスタンスイニシャライザ 2 // コンストラクタ
事例
あるプロジェクトで、開発者はメソッドやコンストラクタの代わりにインスタンスイニシャライザにロジックを配置しました。クラスを継承してコンストラクタをオーバーライドした場合でも、インスタンスイニシャライザは実行され続け、初期化の順序が予期しないものとなり、ビジネスロジックにエラーが発生しました。
事例
別のプロジェクトでは、インスタンスイニシャライザがクラスのフィールドにアクセスしていましたが、そのフィールドはコードの下部で初期化されました。結果として、変数はまだ初期化されておらず、オブジェクトの作成中にNullPointerExceptionが発生しました。
事例
チームはインスタンスイニシャライザに外部リソース(データベース)に関連する操作を追加しました。そのため、各コンストラクタの呼び出しがデータベースへの接続を行い、オブジェクトのバッチ作成時にシステムが過負荷になりました。