web-dev-qa-db-ja.com

プリミティブを含むローカル変数を常にJavaで初期化する必要があるのはなぜですか?

プリミティブを含むローカル変数を常にJavaで初期化する必要があるのはなぜですか?インスタンス変数の場合に同じことが適用できないのはなぜですか?

51
Gourav

基本的に、読む前に変数に値を割り当てる必要があるのは良いことです。これは、意図しないものを誤って読まないことを意味します。はい、変数にはデフォルト値がありますが、まだ割り当てられていない可能性のある何かを読み取ろうとしていることが証明できる場合、コンパイラがバグを代わりにキャッチできる方が良いでしょうか?ローカル変数にデフォルト値を与えたい場合、いつでも明示的に割り当てることができます。

ローカル変数についてはこれで問題ありませんが、インスタンス変数や静的変数については、コンパイラはメソッドが呼び出される順序を知る方法がありません。プロパティ「setter」は「getter」の前に呼び出されますか?知る方法がないので、危険を警告する方法はありません。そのため、デフォルト値がインスタンス/静的変数に使用される-少なくとも、代わりに既知の値(0、false、nullなど)を取得しますちょうど「当時メモリにあったものは何でも」。 (また、明示的にワイプされていない機密データを読み取るという潜在的なセキュリティ問題を取り除きます。)

C#のごく最近のこれに関する質問 ...がありました-基本的に同じことなので、そこの答えも読んでください。 Eric Lippertの最近のブログ投稿 おもしろいかもしれません。推力は多少異なりますが、少なくとも同じエリアの周辺です。

64
Jon Skeet

Javaでは、クラス変数とインスタンス変数は、手動で初期化されない場合、デフォルト値(null、0、false)を想定します。ただし、ローカル変数にはデフォルト値はありません。ローカル変数に値が割り当てられていない限り、コンパイラはそれを読み取るコードのコンパイルを拒否します。私見、これは、ローカル変数を宣言時にデフォルト値(nullなど、後でNullPointerExceptionにつながる可能性がある)で初期化することは実際には悪いことであるという結論に至ります。次の例を考えてみましょう。

_Object o;
if (<some boolean condition>)
  o = <some value>;
else
  o = <some other value>;
System.out.println(o);
_

Nullを使用したoの初期化は完全に不要です。これは、Javaコンパイラがコンパイル時にチェックし、コードパスがo(nullまたは変数が読み込まれる前に、null以外の値)。つまり、変数oの2つの初期化のいずれかをコメントアウトすると、コンパイラはSystem.out.println(o);行のコンパイルを拒否します。上記のコードスニペットで。

これはJavaにも当てはまり、多分Javaのみ。C#のような言語については知りません。古き良きC(およびC++)でも、常に変数を初期化することをお勧めします。このような「古い」プログラミング言語は、常に変数を初期化する推奨事項が、コンパイラーが変数が初期化されているかどうかを追跡するJavaのような現代言語に関する本や議論でポップアップする理由であるかもしれませんありません。

8
Sven

さて、ローカル変数の場合、(メソッド内の)宣言と参照の間のプログラムフローはシーケンシャルであるため、「前」の意味は明確です。メソッドコンパイラの外部で宣言されたフィールドの場合、使用される前に他のメソッドがフィールドを初期化する可能性があるため、エラーを生成できないので、コンパイラはどのコードがいつ使用されるかを認識しません。

8
quosoo

完全に真実ではありません。ローカル変数は、参照されている場合にのみ初期化する必要があります。ローカル変数は、参照されない場合は初期化されないままにすることができます。例えば:

int x;  // Valid
int y;
println("y=" + y);  // Not valid since y's value has never been assigned
6
Steve Kuo

ローカル変数はインスタンス変数のようなデフォルト値を取得しないため、ローカル変数を初期化する必要があります(使用する場合のみ)。

基本的なルールとして、変数を使用する前に必ず初期化する必要があります。そうしないと、nullPointerなどのエラーが発生する可能性があります

さて、なぜローカル変数はデフォルト値を取得しないのですか?その理由は、ローカル変数はスタック上に存在し、ヒープ上に存在し、プログラム全体にスコープを持つインスタンス変数とは異なり、ローカルメソッドコンテキストでのみ表示されるためです。

したがって、スタックが終了すると、ローカルメソッドの値も破棄されます。1]それらは明示的に初期化されることになっています(使用する場合)2]インスタンス変数のように暗黙的に(null、0またはfalseで)初期化されるべきではありません

1
Shashank Bodkhe

ローカル変数とプリミティブは、使用する前に初期化する必要があります。これは、値から何を期待できるかがわかるからです。歴史的に、新しい変数が作成されたとき、メモリからランダムな値が含まれていました[そして、値を予測できませんでした]。 Javaは、孤立した変数の存在を防ぐため、これも必要です。

1
monksy

ローカル変数は、関数内で宣言されるか、関数の引数として渡される状態を示すローカル変数の定義に従います。ローカル変数を初期化しないと、例外処理の問題が発生します。これは、コンパイラが変数が保持する値を理解できないためです。

0
udoh unyime

実際には、すべての変数を使用する前に初期化する必要があります。

値を設定する前に変数を使用したいと思う時間はありません(nullと比較する場合を除く)。

0
James Cronen