90

次のような配列宣言があります。

int a[];

これはプリミティブ型aの配列です。intこの配列はどこに保存されますか? ヒープまたはスタックに保存されますか? これはintプリミティブ型です。すべてのプリミティブ型がヒープに格納されるわけではありません。

4

5 に答える 5

149

グルクルキが言ったように、それはヒープに保存されます。ただし、あなたの投稿は、おそらく「プリミティブは常にスタック上に存在する」という神話を広める善意のある人による誤解を示唆しています。これは真実ではありません。ローカル変数はスタック上に値を持っていますが、すべてのプリミティブ変数がローカルというわけではありません...

たとえば、次のように考えてください。

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 (おそらく実験的なもの) は、オブジェクトがメソッドから決して「エスケープ」しない時期を判断でき、オブジェクト全体をスタックに割り当てることができると思います。ただし、気にすることを選択した場合、概念的にはヒープ上にあります。

于 2010-01-20T07:38:23.197 に答える
39

ヒープに格納されます

配列はJavaのオブジェクトだからです。

編集 :あなたが持っている場合

int [] testScores; 
testScores = new int[4];

このコードは、コンパイラに対して、「4 つの int を保持する配列オブジェクトを作成し、それを という名前の参照変数に割り当てますtestScores。また、各int要素をゼロに設定してください。よろしくお願いします」と考えてください。

于 2010-01-20T07:32:04.757 に答える
25

それ自体はプリミティブではないプリミティブ型の配列です。経験則として、 new キーワードが含まれる場合、結果はヒープ上にあるということです。

于 2010-01-20T07:34:38.977 に答える
21

このテーマで実行したいくつかのテストを共有したかっただけです。

サイズ 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 と表示されます。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;
    }
    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 クラス内の値がヒープに格納されていることを示しています。

于 2013-05-01T21:11:40.170 に答える
2

Java プログラミング言語では、配列はオブジェクトであり、動的に作成され、Object 型の変数に割り当てることができます。

http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html

于 2010-01-20T07:33:32.663 に答える