2011-08-09 10 views
6

で可能な重複を初期化対宣言の初期化:
Should I initialize variable within constructor or outside constructorコンストラクタ

を私はより良い練習と理由である、と思いまして。宣言時にクラスフィールドを初期化するか、コンストラクタでクラスフィールドを初期化する必要がありますか?それが単純な1行の初期化であるとすれば、

class Dude 
{ 
    String name = "El duderino"; 

    Dude() { 
     // irrelevant code 
    } 
} 

class Dude 
{ 
    String name; 

    Dude() { 
     name = "El duderino"; 

     // irrelevant code 
    } 
} 

編集:私はスタイルのいずれかが例外をスローする可能性がある初期化コードを実行する場合のように、他の上で好ましいであろう状況を認識してい。私がここで話しているのは、両方のスタイルが完全に同等である場合です。どちらの方法も同じタスクを達成します。どちらを使うべきですか?

答えて

4

メンバーはのみ可能であればアクセサー( "セッター"メソッド)を介して設定する場合は、私は最初のスタイルを好む。それは、初期化された値が構築時のデフォルト値であるというヒントを提供します。

メンバを構築中に指定できる場合は、一般に、より少ないパラメータでコンストラクタから適切なコンストラクタにデフォルト値を渡します。たとえば、

final class Dude { 

    private final String name; 

    Dude() { 
    this("El Duderino"); 
    } 

    Dude(String name) { 
    this.name = name; 
    } 

} 
+0

これは妥当と聞こえます。しかし、私が話していたのは、どちらの方法でも同じように初期化されるフィールドです。つまり、コンストラクタから取得されたデータは使用されませんでした。サブ要素を格納する空の内部Listを初期化する。あなたはまだそれをコンストラクタで初期化しますか? – amrhassan

+0

@amrhassan - その場合、宣言されたときに初期化する必要はありません。それを 'final'と宣言します。 – erickson

+0

あなたの例で 'final'にする理由を見ることができますが、setter' setName(String name) 'があった場合はどうなりますか? – knownasilya

0

通常、最初の変数は静的変数を初期化するために使用され、その目的にのみ使用されます。

この場合、2番目の方法を使用する必要があります。

私が間違っている場合は、私に修正してください。

+0

最初のフィールドは、静的フィールドがない場合でも問題ありません。それは2番目の合成糖です。 – amit

+0

ええ、私はあなたが意味することを知っています。しかし、もしあなたがC++を使っていれば、静的変数を初期化するために彼が最初にやったことはないことがわかります。これは静的変数を初期化するこの正確な目的のためにjavaに追加されました。 したがって、その目的のために使用する必要があります。 – mtahmed

+0

静的変数の最初のスタイルを予約する理由はありません。あなたはどんな推論を提供することができますか? – erickson

0

一貫性のために、コンストラクタ内で変数を宣言することをお勧めします。変数にはループやif-else文のようなものが必要になることがあります。これを初期化するには、メソッドの内部に操作を置かずに宣言で行うことはできません。

このルールの例外はスタティック変数で、コンストラクタの外側で宣言する必要があります。

+0

初期化ブロックを使用して、メソッドやコンストラクタ内でのみ初期化されるフィールドを初期化することができます。 – emory

0

単一行の宣言に複雑な初期化ロジックを含めることはできません。

あなたのように変数を初期化した場合:

class AnotherClass 
{ 
    MyClass anObject = new MyClass(); //MyClass() throws a checked exception. 
} 

そして、あなたは、単一の行に初期値を提供できないことがわかります。あなたはかなり明らかにコンストラクタ(または非static初期化ブロック内)内部に入るブロック、このようなコードを配置する必要があります:

コンストラクタを使用:

class AnotherClass 
{ 
    MyClass anObject; 

    AnotherClass() 
    { 
     try{this.anObject = new MyClass();}catch(SomeException e){/*handle exception.*/} 
    } 
} 

初期化ブロックを使用します:私は宣言および初期化が互いに分離されているように、後者は、あまり理解コードになり、そして実行時に差がないものの、初期化(開発者がコード化されたコンストラクタで発生していないことが判明

class AnotherClass 
{ 
    MyClass anObject; 

    { 
     try{this.anObject = new MyClass();}catch(SomeException e){/*handle exception.*/} 
    } 
} 

)。

フィールドの初期化に関連する他の複雑なルーチンについても同じことが言えます。あなたがArrayCollectionを初期化し、いくつかのデフォルト値を配列/コレクションの内容を設定する場合たとえば、あなたは、コンストラクタ内でそうする必要があります。

class AnotherClass 
{ 
    Integer[] integers; 

    AnotherClass() 
    { 
     this.integers = new Integer[10]; 
     for(Integer integer: integers) 
     { 
      integer = Integer.MIN_VALUE; 
     } 
    } 
} 
+1

実際には、ここでもイニシャライザブロックを使用することができるので、コンストラクタはこの場合でも唯一可能な方法ではありません – Voo

+0

はい、あまりにも混乱するかもしれません。しかし、それは私の意見です。編集します。 –