nullに割り当てられた変数と割り当てられていない変数のメモリの違いは何ですか


8

nullに割り当てられた変数と割り当てられていない変数のメモリの違いは何ですか?

使用方法に違いがあることは知っていますが、メモリの違いは何ですか?


1
あなたの研究を共有することはすべての人を助けます。何を試したか、なぜそれがニーズを満たさなかったかを教えてください。これは、時間をかけて自分自身を助けようとしたことを示しており、明白な答えを繰り返すことから私たちを救い、そして何よりも、それはあなたがより具体的で適切な答えを得るのに役立ちます。参照してください掲載する方法
GNAT

回答:


11

「メモリ内」の2つの間に違いはありません。

Java言語仕様、4.12.5。変数の初期値

プログラム内のすべての変数には、その値が使用される前に値が必要です。

  • 各クラス変数、インスタンス変数、または配列コンポーネントは、作成時にデフォルト値で初期化されます(§15.9、§15.10.2):

...

    • すべての参照タイプ(4.3)では、デフォルト値はnullです。

...

    • ローカル変数(§14.4、§14.14)は、使用前に、初期化(§14.4)または割り当て(§15.26)によって、明確な割り当てのルールを使用して検証できる方法で、明示的に値を指定する必要があります(§ 16(明確な割り当て))。

クラスまたはオブジェクトレベルの参照変数にはnull値が割り当てられます。

メソッド(スタック)レベルの参照変数は、(C ++用語を使用して)未指定の値になります。実際にはこれは多くの場合nullですが、標準では参照変数の内容を指定しいません。使用する前に割り当てる必要があることだけを指定しています。スタック上の参照変数を最初の使用として割り当て以外の方法で使用すると、コンパイルエラーが発生します。


変数をnullに初期化せずに宣言し、if-thenブロック内で初期化すると、thenブロックが実行されない場合、コードの前で変数が初期化されていない可能性があることがコンパイラーから通知されます。初期化するとnullコードがコンパイルされます。「明示的に値が割り当てられていない参照が値nullを持っている」とすると、それはなぜですか?
TulainsCórdova2015

@スノーマンそれは実装の詳細ではないですか?クラス変数、インスタンス変数、および配列コンポーネントのみをデフォルト値に初期化する必要があります。ローカル変数の要件はなく、初期化する前に使用することはできません。メモリ内の初期化されていないローカル変数を見ると、実装がそれを使って何をするかがわかりますnull。これを行うのは不必要な作業なので、初期化する必要はありません。
Doval

@Snowman-値が割り当てられる前にローカル事前変数を使用することは違法であるため、初期化されていないローカル変数に初期値が指定されているかどうかは、実装の詳細です。
David Hammen、2015

1
私の最新の編集をご覧ください。月曜日の朝に不十分なコーヒーのせいにしました。

4

nullに割り当てられた変数とメモリに割り当てられていない他の変数の違いは何ですか?

Javaには、割り当てられていない変数などはありません。明示的な割り当てがないクラスデータメンバーには、型のデフォルト値、オブジェクトのnull、またはプリミティブ型の0に似たものが割り当てられます。

ローカル変数はスタック上にあります。(MyType foo参照として、スタック上にも存在するような非プリミティブローカル)スタックの割り当ては単純です。ブロックにローカル変数の宣言が含まれている場合、それらのローカル変数に必要なスペースはスタック上に予約されます。スタックを調整してそれらのローカル変数に対応する際に、それらのローカル変数に値を割り当てるかどうかは関係ありません。

重要ではない理由は、実行がブロックに入るときにローカル変数に値が割り当てられているかどうかが2つあるためです。1つの理由は、必要なサイズが変化しないことです。プリミティブのサイズは固定されており、非プリミティブは実際には参照です。(参照されるオブジェクトは、スタックではなくヒープ上に存在します。)2番目の理由は、値が割り当てられていないローカル変数を使用すると、コンパイルエラーが発生するためです。これにより、宣言されているが割り当てられていないローカル変数に値(必ずしもデフォルトではない)を与えるかどうかは、Javaランタイム次第です。


あなたの答えのどこかにこれの説明があります:nullに初期化せずに変数を宣言し、if-thenブロック内で初期化すると、thenブロックが実行されない場合、コードの前で変数が初期化されていない可能性があるとコンパイラーは伝えます。初期化するとnullコードがコンパイルされます。「明示的に値が割り当てられていない参照が値nullを持っている」とすると、それはなぜですか?しかし、それは私にはまだ十分に明確ではありません。言い換えれば、それを説明できますか?
TulainsCórdova2015

2
ローカル変数に初期値を与える必要はありません。最初に使用する前に値を割り当てる必要があります。割り当てのない宣言の場合でも、その変数に関連付けられたメモリに明示的な初期値が与えられるかどうかは、実装の詳細です。メモリは存在します(それがスタックの動作方法です)が、スタックを調整する前に、そのメモリ空間にそのメモリ内に何が起こっていても満たすことができます。
David Hammen、2015

@ user61852- 明示的に値が割り当てられていない参照が値nullを持つことは、クラスメンバーに対してはtrueですが、ローカル変数に対しては必ずしもそうではありません。デバッグを有効にしてコードをコンパイルする場合、コンパイラーはほとんどの場合、初期化されていない非プリミティブローカル変数をに初期化しますnull。これにより、Javaデバッガの開発が大幅に簡素化されます。しかし、デバッグを無効にしてコンパイルするとどうなるでしょうか。これで、初期化は不要な余分な作業です。メモリーには最初の使用時に有効な値が含まれることがわかっているため、そのメモリーの内容は無関係です。
David Hammen、2015

バイトコードの観点から、ローカル変数はスタックに割り当てられます。ただし、JITterは、特定のスタックエントリを実際にスタックに格納するのではなく、そのエントリへのストアとそのエントリからのロードを特定のCPUレジスタに向けるように決定する場合があります。さらに、JITterは、実行が特定のポイントに到達すると、スタックエントリが書き換えられずに読み込まれる方法がないと判断した場合、他の目的のためにそのエントリの関連レジスタを再割り当てすることがあります。
スーパーキャット2015

1

まず、ローカル変数が使用するスペースについて心配する必要はありません。1行で100,000整数の配列を割り当てることができます。これは、これから使用するすべてのローカル変数よりも多くのスペースを必要とします。

第二に、あなたのコードは賢い可能性が高いコンパイラによってコンパイルされます。変数が初期化されていない場合、それは使用されません(コンパイラーが初期化されていない変数の使用を許可していないため)。しかし、それをnilに初期化しても、まだ使用されていません。コンパイラーは、それが使用されておらず、実際には変数にスペースをまったく使用していないことを容易に理解します。これを使用しても、コンパイラは値がnilであることを簡単に判断し、変数の代わりにnilを使用します。

しかし、3番目に、これはすべてプログラムを最適化するのに役立つわけではないすべてのマイクロ最適化です。4バイトまたは8バイトを保存しようとしています。何かを保存したい場合は、メガバイトの節約に集中してください。

そして最後に、変数を常に初期化する必要があると主張する人もいますが、Javaではそうではありません。変数には意味のある値のみを設定してください。変数に人物の名前を設定したいとし、1つのコードパスでこれを行うのを忘れたとします。変数を盲目的にnilに初期化すると、コンパイラーはそれを通知できません。初期化を行わない場合、コンパイラは間違いを教えてくれます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.