Java クラスを定義すると、次のようになります。
class A {
private String str = "init method 1";
public A() {
str = "init method 2";
}
}
str
定義時に初期化するか、コンストラクターで初期化できます。私の質問は、2 つの方法の違いは何ですか? どの方法が好まれますか?
Java クラスを定義すると、次のようになります。
class A {
private String str = "init method 1";
public A() {
str = "init method 2";
}
}
str
定義時に初期化するか、コンストラクターで初期化できます。私の質問は、2 つの方法の違いは何ですか? どの方法が好まれますか?
初期化ブロックの値は、コンストラクターが割り当てる前に割り当てられます。
したがって、値init member 1
は最初に割り当てられ、次にinit member 2
割り当てられます。
theJavaGeek のこの例を考えてみましょう
class InitBlocksDemo {
private String name ;
InitBlocksDemo(int x) {
System.out.println("In 1 argument constructor, name = " + this.name);
}
InitBlocksDemo() {
name = "prasad";
System.out.println("In no argument constructor, name = " + this.name);
}
/* First static initialization block */
static {
System.out.println("In first static init block ");
}
/* First instance initialization block */
{
System.out.println("In first instance init block, name = " + this.name);
}
/* Second instance initialization block */
{
System.out.println("In second instance init block, name = " + this.name);
}
/* Second static initialization block */
static {
System.out.println("In second static int block ");
}
public static void main(String args[]) {
new InitBlocksDemo();
new InitBlocksDemo();
new InitBlocksDemo(7);
}
}
これは、
In first static init block
In second static int block
In first instance init block, name = null
In second instance init block, name = null
In no argument constructor, name = prasad
In first instance init block, name = null
In second instance init block, name = null
In no argument constructor, name = prasad
In first instance init block, name = null
In second instance init block, name = null
In 1 argument constructor, name = null
プログラムの流れは以下の通りです。
InitBlocksDemo
が JVM にロードされます。main
メソッドが検出されます。new InitBlocksDemo();
により、引数のないコンストラクターが呼び出されます。super
引数 のないコンストラクターへのデフォルトの呼び出しがあるため、制御はスーパークラス、つまりObject
クラスに移動しますnull
。null
new InitBlocksDemo(7);
により、引数が 1 つのコンストラクターが呼び出されます。残りのプロセスは同じです。唯一の違いは、名前が新しい値に再割り当てされないため、出力されることですnull
違いは、割り当てがいつ行われるかです。コンストラクターが実行される前にフィールドに const 値が割り当てられるため、コンストラクターに次の行を追加すると、次のようになります。
System.out.println(str);
コンストラクターで新しい値を割り当てる前に、古い値がそこにあることがわかります。
それ以外に大きな違いはなく、どちらを使用するかはほとんど個人的な好みです。
個人的には、フィールド宣言の一部として直接割り当てることができるものは何でも - それが私がしていることです。
それらの間に違いはありません。コンパイラは初期化ブロックをコンストラクタにコピーします
クラス用に生成されたクラス ファイルを逆コンパイルする場合
class A {
private String str1 = "init method 1";
private String str2;
public A() {
str2 = "init method 2";
}
public A(String str2) {
str2 = str2;
}
}
発見できる
class A
{
private String str1;
private String str2;
public A()
{
str1 = "init method 1";
str2 = "init method 2";
}
public A(String str2)
{
str1 = "init method 1";
str2 = str2;
}
}
私の個人的な経験では、オブジェクトの初期化がどれほど高価であるか、または詳細であるかがすべてです。第二に、怠惰な作成と能動的な作成とを考えることもできます。コンストラクターのみが関与する場合、通常はインスタンス変数レベルでオブジェクトを作成します。問題のメンバーを初期化するための呼び出しがさらにある場合、呼び出しは確実にコンストラクターまたは初期化が必要なメソッドに移動されます。
そのため、ファクトリ メソッド パターンを使用して、実際のオブジェクトの作成を別のクラスに委譲します。