如果我有一个函数,我在该函数中声明:
Object arr[] = new Object[20];
arr和整个数组存储在哪里?堆?堆? 声明是在某个函数中还是在main()中是否重要?
让我说我也有这些命令行:
arr[0] = new String("abc");
arr[1] = new List();
arr[0]
和arr[1]
存放在哪里?
答案 0 :(得分:13)
记忆图:
框是内存位置(可以存储二进制数) 箭头是内存引用(即指针)。
答案 1 :(得分:8)
理论上,堆栈有一个指向堆中包含数组本身的位置的指针。数组本身只是一个指针数组,它也指向堆中包含您引用的对象的位置。
在Java中,您可以非常依赖这样一个事实:只要您说new ...
,就会在堆中创建空间。一般来说,只要声明变量,编译器就会在方法的上下文中为该变量保留堆栈空间。对于本机类型,该空间将保存实际字节以表示该值。对于对象和数组,该变量将保存内存引用。
因此,例如,以下对象在堆中为它们分配了单独的内存位置:
new Object[20]
new String("abc")
new List() // This contains a reference to an initial array, which is also on the heap.
请注意,new String("abc")
优于"abc"
的次数很少,因为字符串文字无论如何都会存在于包的内存中,并且字符串是不可变的。没有必要为内存中存在的字符串的精确副本分配额外的内存。
实际上,唯一需要注意的是编译器根本不必将局部变量存储在堆栈中。如果确定变量的范围足够短,则可以自由地优化掉堆栈引用,只需使用寄存器即可。
答案 2 :(得分:5)
在Java中,基本上每次使用new
关键字时,都要在堆上为要存储的对象分配空间。
用于指向该对象的变量包含存储在堆栈中的引用。
例如:
// This array object is
// stored on the heap.
String[] arr = new String[5];
// This reference (arr) is stored
// in a variable on the stack.
对于像Object[]
这样的引用类型数组,分配的空间是一个足够大的连续块,可以存储数组所包含的引用。任何特定的引用(例如arr[0]
处的引用)本身都指向堆上存储单个对象的另一个位置。
The array, somewhere on the heap:
[a*][b*][ ][ ][ ]
a (elsewhere on the heap):
"abc"
b (yet another heap location):
[A List object]
唯一的例外是基元数组,如int[]
:在这种情况下,数组本身仍然是堆上的连续块,但数组中的每个位置都包含实际值本身而不是引用堆上的另一个位置。
答案 3 :(得分:0)
n 字符串数组
此Array也有一个引用,可以保存在堆栈中或(作为类中的字段)在堆
中