言い換えれば、なぜインスタンス初期化子が必要なのですか?コンストラクターに対してインスタンス初期化子を作成することには、どのような違いまたは利点がありますか?
回答:
これはそれをうまく説明しているようです:
インスタンス初期化子は、次の場合にインスタンス変数初期化子の便利な代替手段です。
初期化コードは例外をキャッチする必要があります、または
インスタンス変数の初期化子では表現できない凝った計算を実行します。もちろん、いつでもコンストラクターでそのようなコードを書くことができます。
ただし、複数のコンストラクターを持つクラスでは、各コンストラクターでコードを繰り返す必要があります。インスタンス初期化子を使用すると、コードを1回記述するだけで、オブジェクトの作成に使用されるコンストラクターに関係なく実行されます。インスタンス初期化子は、コンストラクターをまったく宣言できない匿名の内部クラスでも役立ちます。
From:JavaでのJavaWorldオブジェクトの初期化。
オブジェクトのライフサイクルに関しては、違いはありません。どちらも構築時に呼び出され、論理的には初期化ブロックは構築の一部と見なすことができます。
意味的には、イニシャライザはいくつかの理由で便利なツールです。
初期化子は、初期化される変数の横に初期化ロジックを保持することにより、コードの可読性を向上させることができます。
public class Universe {
public int theAnswer;
{
int SIX = 6;
int NINE = 7;
theAnswer = SIX * NINE;
}
// a bunch of other vars
}
vs
public class Universe {
public int theAnswer;
// a bunch of other vars
public Universe() {
int SIX = 6;
int NINE = 7;
theAnswer = SIX * NINE;
// other constructor logic
}
}
イニシャライザーは、使用されているコンストラクターに関係なく呼び出されます。
イニシャライザーは、コンストラクターでは使用できない匿名の内部クラスで使用できます。
theAnswer
は、宣言されたインスタンス変数です。匿名の初期化ブロックで初期化されます。変数宣言の後のセミコロンに注意してください。
コンストラクターが多数あり、コンストラクターごとに共通のコードを実行する場合は、インスタンス初期化子を使用できます。これは、すべてのコンストラクターに対して呼び出されるためです。
私は一般的にインスタンス初期化イディオムを避けます-それが変数初期化子に対して与える唯一の本当の利点は例外処理です。
また、initメソッド(コンストラクターから呼び出し可能)も例外処理を実行でき、コンストラクターのセットアップコードを一元化できますが、コンストラクターのパラメーター値を操作できるという利点があるため、インスタンス初期化子は冗長であると言えます。避けた。
オブジェクト作成時にインスタンス変数の初期化を実行する場合は、コンストラクターを選択する必要があります。オブジェクト作成時にアクティビティを実行する場合は、初期化アクティビティ以外に、インスタンスブロックを実行する必要があります。
コンストラクターは引数を取ることができますが、インスタンスブロックは引数を取ることができないため、コンストラクターをインスタンスブロックに置き換えることはできません。
クラスには複数のコンストラクターを含めることができるため、インスタンスブロックをコンストラクターで置き換えることはできません。インスタンスブロックをコンストラクターに置き換えたい場合は、すべてのコンストラクターでインスタンスブロックコードを作成する必要があります。これは、実行時にどのコンストラクターが呼び出されるかを予期できないため、重複コードが不必要に増えるためです。
例:
class MyClass{
static int object_count = 0;
MyClass(){
object_count++;
}
MyClass(int i){
object_count++;
}
void getCount() {
System.out.println(object_count);
}
public static void main(String... args) {
MyClass one = new MyClass();
MyClass two = new MyClass(2);
two.getCount();
}
}
出力: 2
class MyClass{
static int object_count = 0;
{
object_count++;
}
MyClass(){
}
MyClass(int i){
}
void getCount() {
System.out.println(object_count);
}
public static void main(String... args) {
MyClass one = new MyClass();
MyClass two = new MyClass(2);
two.getCount();
}
}
出力: 2
イニシャライザーはコンストラクター間でコードを共有する方法であり、イニシャライザーを変数宣言とともに使用すると、コードが読みやすくなります。
Javaコンパイラは、初期化ブロックをすべてのコンストラクタにコピーします。したがって、このアプローチを使用して、複数のコンストラクター間でコードのブロックを共有できます。 Oracleのドキュメント