看了很多网上的资料,对于堆和栈的解释,大体上都是说基本数据类型的变量是在栈内存中,引用类型变量都存放在堆内存中。是不是正确呢,我这么认为,不一定完全准确,可能有误导的成份。
首先,什么是堆内存(heap),什么是栈内存(stack)。
堆:JAVA虚拟机(JVM)启动时分配的一块永久的、很大的内存区,而且堆内存在一个程序中只有一块。
栈:每次方法运行时分配一块临时的、很小的内存区。
那么到底什么东西是放在堆里,什么东西是放在栈里呢?
1、new出来的东西即对象,都放在堆内存里;
2、基本数据类型变量及数据存在栈内存中;
3、引用类型变量名是存在栈内存中;
那基本类型和引用类型的变量是如何赋值的,在内存中如何体现?
1、基本类型变量赋值:直接将该值存入变量所在的内存,即栈内存;
2、引用类型变量赋值:将该变量所指向的对象的第一个内存单元编号(即对象在堆内存中的首地址)存入变量内存区中(即栈内存中)。
public class test{
public static void main(String[] args){
int a = 20;
int b = a;
System.out.println("a:"+a);
System.out.println("b:"+b);
b = 13;
System.out.println("a:"+a);
System.out.println("b:"+b);
}
}
输出结果是:
a:20
b:20
a:20
b:13
这里是基本数据类型的赋值,各自数据的变化并不相互影响。
int[] arr = new int[]{20};
int[] brr = arr;
System.out.println("arr[0]:"+arr[0]);
System.out.println("brr[0]:"+brr[0]);
brr[0] = 13;
System.out.println("arr[0]:"+arr[0]);
System.out.println("brr[0]:"+brr[0]);
输出结果是:
arr[0]:20
brr[0]:20
arr[0]:13
brr[0]:13
再看上面这一段简单的代码,第一对20都好理解,arr[ ]的引用对象赋给brr[ ]即arr和brr指向同一个对象,因此输出结果都是20;
但是为什么执行brr[0] = 13;这一句代码后,两者的数据都发生了变化呢?
首先,要理解清楚这一个简单赋值语句,其实是关键所在,因为brr[ ]引用对象没有发生变化,仍然是arr[ ]所指向的对象,但是brr[0] = 13将brr所指向的对象的首地址存放的数据20强行改为13,因此,arr[0]和brr[0]这个时候都变成13,这样大家应该能理解了吧。
但如果上述的代码这么改一下的话,结果会是什么呢?
int[] arr = new int[]{20};
int[] brr = arr;
System.out.println("arr[0]:"+arr[0]);
System.out.println("brr[0]:"+brr[0]);
brr=new int[]{13};
System.out.println("arr[0]:"+arr[0]);
System.out.println("brr[0]:"+brr[0]);
输出结果是:
arr[0]:20
brr[0]:20
arr[0]:20
brr[0]:13
这里输出结果就跟上面不一样了,arr的值仍是20,而brr的值就变为13了,因为arr仍是引用原来的对象,其数据没有发生变化,而brr数组引用指向了一个新new 的对象(在堆内存中重新开辟一块内存空间,与arr指向的对象内存空间不一致)。
如果有误,请大神勿喷,初学小白,学识尚浅,望各位多指导。