JAVA中的堆和栈
- 堆和栈的简单描述
- 栈
- 堆
- 示例1
- 示例2
- 如何判断操作的是原始对象本身还是引用地址的变量(个人理解,仅作为记录)
引言
在Java中,内存管理是一个重要的概念,它涉及到堆(Heap)和栈(Stack)两种主要的内存区域。理解这两者对于编写高效、稳定的Java代码至关重要。
堆和栈的简单描述
栈
函数中定义的基本类型变量,对象的引用变量都在函数的栈内存中分配。
栈内存中存储的是对象的引用地址,栈内存中的数据,没有默认初始化值,需要手动设置。栈内存特点,数据一执行完毕,变量会立即释放,节约内存空间。
堆
堆内存用来存放new创建的对象和数组。
堆内存中所有的实体都有内存地址值。
堆内存中的实体不再被指向时,JVM启动垃圾回收机制,自动清除,这也是JAVA优于C++的表现之一(C++中需要程序员手动清除)。
示例1
public static void main(String[] args) {
List<ModelUploadParam> list = new ArrayList<>();
test(list);
System.out.println(list);
}
static void test(List<ModelUploadParam> list){
list = null;
System.out.println(list);
}
第一步:执行main函数,定义list集合,在栈内存中开辟一个空间存放list变量,同时,在堆内存中也开辟一个空间存放ArrayList对象,堆内存会自动分配地址值,如0x0045。
第二部:执行test函数,传递list的引用拷贝,方法参数传递机制是按值传递(pass-by-value)
第三步:对test函数中list赋null,修改的是方法内部引用的副本,只改变了引用变量的指向,并没有改变原始引用或堆中的对象。原始引用仍然指向最初的对象,因此原始对象不会受到影响。
示例2
public static void main(String[] args) {
List<ModelUploadParam> list = new ArrayList<>();
test(list);
System.out.println(list);
}
static void test(List<ModelUploadParam> list){
list.clear();
System.out.println(list);
}
与实例1不同的是,list.clear()修改的是堆中的对象内容,因为调用的是对象的方法。无论是原始引用还是方法内部的引用,指向的都是同一个堆中的对象,因此修改后会影响原始对象。
如何判断操作的是原始对象本身还是引用地址的变量(个人理解,仅作为记录)
list.
调用的是引用所指向的原始对象的方法或属性。这意味着对对象本身的操作,比如 list.clear() 或 list.add(),会影响到引用所指向的那个对象,因为它们操作的是堆中的对象内容。list =
修改的是引用地址。这意味着你在改变引用变量本身,让它指向另一个对象或者 null,但不会影响到原始对象或其他引用指向该对象。