原语的Java数组存储在堆栈还是堆中?

原语的Java数组存储在堆栈还是堆中?,java,arrays,stack,heap,primitive-types,Java,Arrays,Stack,Heap,Primitive Types,我有这样一个数组声明: int a[]; 这里是一个基本int类型的数组。这个数组存储在哪里?它是存储在堆上还是堆栈上?这是一个primitve类型int,所有的基元类型都不存储在堆上。它将存储在堆上 因为数组在java中是一个对象 编辑:如果你有 int [] testScores; testScores = new int[4]; 将这段代码想象为对编译器说,创建一个包含四个整数的数组对象,并将其分配给名为testScores的引用变量。另外,继续并将每个int元素设置为零。谢谢。在J

我有这样一个数组声明:

int a[];
这里是一个基本int类型的数组。这个数组存储在哪里?它是存储在堆上还是堆栈上?这是一个primitve类型int,所有的基元类型都不存储在堆上。

它将存储在堆上

因为数组在java中是一个对象

编辑:如果你有

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

将这段代码想象为对编译器说,创建一个包含四个整数的数组对象,并将其分配给名为testScores的引用变量。另外,继续并将每个int元素设置为零。谢谢。

在Java编程语言中,数组是对象,是动态创建的,可以分配给Object类型的变量


它是一个基元类型数组,其本身不是基元类型。一个好的经验法则是,当涉及新关键字时,结果将在堆上。

正如gurukulki所说,它存储在堆上。然而,你的帖子暗示了一个误解,可能是因为一些好心人宣扬原始人总是生活在堆栈上的神话。这是不真实的。局部变量的值在堆栈上,但不是所有的基元变量都是局部变量

例如,考虑这一点:

public class Foo
{
    int value;
}
...

public void someOtherMethod()
{
    Foo f = new Foo();
    ...
}
现在,f.value住在哪里?神话可能暗示它在堆栈上,但实际上它是新Foo对象的一部分,并且生活在heap1上。请注意,f本身的值是一个引用,并且存在于堆栈中

从这里开始,很容易找到阵列。你可以把数组看作是很多变量——所以新的int[3]有点像有这样一个类:

public class ArrayInt3
{
    public readonly int length = 3;
    public int value0;
    public int value1;
    public int value2;
}

事实上,它比这更复杂。堆栈/堆的区别主要是一个实现细节——我相信一些JVM(可能是实验JVM)可以判断对象何时从不从方法中逃逸,并且可以在堆栈上分配整个对象。但是,如果你愿意的话,它在概念上是堆上的。

我只想分享我在这个主题上运行的几个测试

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
------------------------
如您所见,使用的堆大小增加了约80MB,即10m*sizeofdouble

但是如果我们用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();
}
相当于

a[i] = Double.valueOf(qq.doubleValue());
a[i] = new Double(qq.doubleValue());
这相当于

a[i] = Double.valueOf(qq.doubleValue());
a[i] = new Double(qq.doubleValue());
因为我们每次都会创建新的双对象,所以我们会吹出堆。
这表明Double类中的值存储在heap中。

这不是数组。它是对数组的引用。如果引用本身是类或对象的成员,则可以将其存储在堆上;如果引用本身是方法中的局部变量,则可以将其存储在堆栈上。如果基元类型是类或对象的成员,则它们可以存储在堆上。堆上数组的名为testScorespointing的引用变量将位于堆栈上。只有在向编译器提供-g选项时,代码才会显示感谢。否则它将被优化掉。@mob您假设这是唯一的代码。假设这两行代码是实际使用数组的大型程序的一部分可能更好。关于Java中的转义分析:它说,它自JDK 6 Update 14的早期access发行版起就存在,并在JDK 6 Update 23的默认情况下启用。如果数组是公共静态final,它会改变什么吗?那么它不应该是固定池的一部分吗?@Malachiasz:不。数组从来都不是常量。@JonSkeet:据我所知,在Java库的所有版本中,每个字符串都有一个char[]作为后盾。我相信文字字符串存储在公共常量池中;对于GC优化,这意味着应该同样存储备份阵列,否则必须在任何GC循环期间扫描常量池,否则备份阵列将有资格收集。@supercat:是的,这是有意义的。但是你声明的任何数组都不会成为常量池的一部分。你能粘贴memInfo的代码细节吗