私はこのような配列宣言を持っています:
int a[];
これa
がプリミティブint
型の配列です。この配列はどこに保存されますか?ヒープまたはスタックに格納されていますか?これはint
プリミティブ型であり、すべてのプリミティブ型がヒープに格納されるわけではありません。
私はこのような配列宣言を持っています:
int a[];
これa
がプリミティブint
型の配列です。この配列はどこに保存されますか?ヒープまたはスタックに格納されていますか?これはint
プリミティブ型であり、すべてのプリミティブ型がヒープに格納されるわけではありません。
回答:
gurukulkiが言ったように、それはヒープに保存されます。しかし、あなたの投稿は、おそらく「プリミティブは常にスタックに住んでいる」という神話を広めている善意のある人による誤解を示唆していました。これは真実ではありません。ローカル変数の値はスタックにありますが、すべてのプリミティブ変数がローカルであるとは限りません。
たとえば、次のことを考慮してください。
public class Foo
{
int value;
}
...
public void someOtherMethod()
{
Foo f = new Foo();
...
}
さて、どこにf.value
住んでいますか?神話はそれがスタック上にあることを示唆しますが、実際にはそれは新しいFoo
オブジェクトの一部であり、ヒープ1上に存在します。(f
それ自体の値は参照であり、スタック上に存在することに注意してください。)
そこから、配列への簡単なステップです。配列は単なる多くの変数であると考えることができます-したがってnew int[3]
、この形式のクラスを持つことに少し似ています:
public class ArrayInt3
{
public readonly int length = 3;
public int value0;
public int value1;
public int value2;
}
1実際、これよりも複雑です。スタック/ヒープの区別は、ほとんどが実装の詳細です。一部のJVMは、おそらく実験的なものであり、オブジェクトがメソッドから「エスケープ」されないことを認識でき、オブジェクト全体をスタックに割り当てる可能性があると思います。ただし、気にすることを選択した場合、概念的にはヒープ上にあります。
String
がchar[]
。によって支えられています。リテラル文字列はパブリック定数プールに格納されていると思います。GC最適化の場合、これはバッキングアレイも同様に格納する必要があることを意味します(そうでない場合、バッキングアレイが収集の対象となるGCサイクル中に定数プールをスキャンする必要があります)。
ヒープに格納されます
配列はJavaのオブジェクトだからです。
編集 :あなたが持っている場合
int [] testScores;
testScores = new int[4];
このコードは、コンパイラに「4つのintを保持する配列オブジェクトを作成し、それをという名前の参照変数に割り当てますtestScores
。また、各int
要素をゼロに設定します。ありがとう」と考えてください。
-g
コンパイラにオプションを指定した場合にのみ、コードに「ありがとう」と表示されます。それ以外の場合は、最適化されます。
これは、それ自体がプリミティブではないプリミティブ型の配列です。経験則として、新しいキーワードが含まれると、結果はヒープに表示されます。
このテーマで実行したいくつかのテストを共有したかっただけです。
サイズ1000万の配列
public static void main(String[] args) {
memInfo();
double a[] = new double[10000000];
memInfo();
}
出力:
------------------------
max mem = 130.0 MB
total mem = 85.0 MB
free mem = 83.6 MB
used mem = 1.4 MB
------------------------
------------------------
max mem = 130.0 MB
total mem = 130.0 MB
free mem = 48.9 MB
used mem = 81.1 MB
------------------------
ご覧のとおり、使用済みヒープサイズは約80 MB増加します。これは、10m * sizeof(double)です。
しかし、doubleの代わりにDoubleを使用している場合
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
memInfo();
}
出力には40MBが表示されます。二重参照のみがあり、初期化されていません。
ダブルで埋める
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
Double qq = 3.1d;
for (int i = 0; i < a.length; i++) {
a[i] = qq;
}
memInfo();
}
それでも40MB。それらはすべて同じDoubleオブジェクトを指しているからです。
代わりにdoubleで初期化
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
Double qq = 3.1d;
for (int i = 0; i < a.length; i++) {
a[i] = qq.doubleValue();
}
memInfo();
}
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
ライン
a[i] = qq.doubleValue();
と同等です
a[i] = Double.valueOf(qq.doubleValue());
これは
a[i] = new Double(qq.doubleValue());
毎回新しいDoubleオブジェクトを作成するので、ヒープを吹き飛ばします。これは、Doubleクラス内の値がヒープに格納されていることを示しています。
Javaプログラミング言語では、配列はオブジェクトであり、動的に作成され、Object型の変数に割り当てることができます。
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html