2011-12-22 7 views
4

私は非常に基本的な問題を抱えています。存在しなければならないにもかかわらず解決策を見つけることができませんでした。Javaのunitializedオブジェクトがnullに設定されていないのはなぜですか?

私は、次のコードを持っている:それは '

を '変数が初期化されていない可能性があります'' 私に

を与える

public class Foo { 
    public static void main(String[] args) { 
     String foo; 
     if (foo != null) { 
      System.out.println("foo"); 
     } else { 
      System.out.println("foo2"); 
     } 
    } 
} 

を。なぜ私はnullを明示的に割り当てる必要があり、すべての変数がデフォルトでnullで初期化されるわけではないのですか?

+2

それは物事がある方法ですので、あなたならば...クラスレベルで –

+1

のみメンバ変数を自動的に初期化されますそれらを明示的に初期化しないでください。ローカル変数は自動的には初期化されません。これらはJavaプログラミング言語の単なるルールです。 – Jesper

答えて

15

ローカル変数が間違って割り当てられる前に、を使用して偶発的にからあなたを防ぎます。これは良いものです - それはバグを防ぐのに役立ちます。フィールド(インスタンス変数と静的変数)では実行できないことは残念ですが、最終的な変数以外では、コンパイラはいつそれらを読み込むのか、それを割り当てるのかは分かりません。メソッドを呼び出す順序を伝えることはできません。 1つのメソッド内では、フローコントロールに関する情報がより多く含まれているため、より多くのチェックを行うことができます。

あなただけの明示的は、それがnullにを設定していないなぜあなたは、ローカル変数の値がnullになりたい場合は?これは、コンパイラを幸せに保つだけでなく、あなたの意図が何であるかを明確にします。

明確な割り当ての詳細については、chapter 16 of the Java Language Specificationを参照してください。コレクションが空の場合はどうするか

Iterable<String> collectionOfNames = ...; // Some method call 
String lastNameInCollection; 
for (String name : collectionOfNames) 
{ 
    lastNameInCollection = name; 
} 
System.out.println("The last name was: " + lastNameInCollection); 

:ここ

は、それがバグを防ぐことができる方法の例ですか? たぶん私たちは "姓は:null"でしたが、何か他のことをする必要があります。上記がコンパイルされない(lastNameIncollectionが割り当てられない可能性がある)という事実は、名前の集合が空である場合についてプログラマに考えることを強いる。

+0

質問には答えられないと思います。なぜコンパイラーが文句を言っているのではないのですが、なぜローカル変数がクラスのメンバーのようにデフォルト値で自動的に初期化されないのか、なぜそれを明示的に行う必要があるのでしょうか。 – Reboot

+2

@Reboot:いいえ、私は説明しました。なぜなら、値を与えられる前に誤って使用することを避けるためです。 –

+0

ローカル変数にデフォルト値が割り当てられている場合、問題は最初に存在しません。それは問題です:なぜローカル変数はデフォルト値に割り当てられていませんか?したがって、コンパイラがunitialized値を使用できない理由を説明しても、変数を手動で初期化する必要がある理由は説明されていません。 – Reboot

1

単純な回答は
メンバーのローカル変数は 'null'値で自動初期化されません。 しかし、クラスメンバ変数はです。あなたがこの主題の完全な深い理解はジョンスキートの答えを考えると、彼は提供されたリンクをチェック取得したい場合は

このコードは

public class Foo { 
    String foo; 
    public static void main(String[] args) { 
    if (foo != null) { 
     System.out.println("foo"); 
    } else { 
     System.out.println("foo2"); 
    } 
    } 
} 

またはこの1

public class Foo { 
    public static void main(String[] args) { 
    String foo = null; 
    if (foo != null) { 
     System.out.println("foo"); 
    } else { 
     System.out.println("foo2"); 
    } 
    } 
} 

に動作します。また、それは間違いなく、後に初期化されている場合、それを初期化する完全に不要にすることができ

1

String foo; 
    if (specialUseCase) { 
     foo = "this"; 
    } else { 
     foo = "that"; 
    } 
-1

ローカル変数は自動的に初期化されていないとして、あなたは明示的にメンバ変数に初期化されているthem.Onlyを初期化する必要がありますnullまたは明示的に初期化していない場合でもデフォルト値。String foo;をmain()メソッドの外側に置くと、初期化する必要はありません。

2

変数を初期化しないと、コードを使用する前にコードの可能なすべての分岐に割り当てられていることをコンパイラが確認できるようにすることができます。あなたは枝の一つに変数を割り当てることを忘れた場合は、コンパイラは文句を言うでしょう

String variable; 
if (conditionA) { 
    if (conditionB) 
     variable = "B"; 
    else 
     variable = "A"; 
} else { 
    switch (conditionC) { 
    case 1: 
     variable = "C1"; 
     break; 
    case 2: 
     variable = "C2"; 
     break; 
    default: 
     variable = "CD"; 
     break; 
    } 
} 
System.out.println(variable.length()); 

:たとえば、あなたは、変数を割り当て、nullてはいけません、複雑な条件を持っている場合。 nullを割り当てないことがわかっているので、変数nullを確認せずに変数を安全に使用できます。あなたが定義でnullで変数を初期化し、コンパイラはこれをチェックすることはできません値に変数を設定することを忘れて、あなたが得ることができる場合NullPointerException

String variable = null; 
if (conditionA) 
    variable = "A"; 
// NullPointerException if conditionA is false, not check by compiler 
System.out.println(variable.length()); 

変数は、最終的な可能性があり、この場合、1回のみ割り当てることができます。あなたはデフォルト値で初期化したい場合は、それがすでに割り当てられているだろうと再割り当てすることはできません。

final int variable; 
if (condition) 
    variable = 1; 
else 
    variable = 2; 
関連する問題