首先要理解应用和对象两个概念。
对象这个概念,相信会编程都了解,对象就是: “数据”加上“操作数据的方法”。对于机器来说,一个对象就是一块内存,里面存了数据。(类的定义(方法/静态变量)是单独存的,这里不将它认为是对象的一部分)。
这个对象的内存里存了什么数据呢? 就是这个对象的实例变量(或者叫成员变量)。(不考虑java中对象的一些其它的头信息)
实例变量有些啥?所有的基本类型 和引用类型。一般的Java入门书里可能不会提到引用类型,一般说java虚拟机的书才会提到。引用类型占4个字节,存放的数据是对象的引用(内存地址)。 学过C的人很容易将引用类型和指针联系起来。
任何一个对象,都至少有一个引用(没有引用的对象都将会被垃圾回收器回收)。这些引用的数据类型就是引用类型。
public class Test {
private Object instanceVariable = new Object();
private int instanceVariableInt;
public void method() {
Object localVariable = this.instanceVariable; // 假设程序刚执行完这一行
}
}
我们来看上面的类,简单的认为这个类有两个实例变量,instanceVariable为引用类型,存放的是一个对象的引用(内存地址)。instanceVariable作为实例的一部分,存在堆内存中, 然而他引用的对象则在堆内存中的另外一个块内存区域。
上面类中的localVariable也是引用类型,它是局部变量,它不是对象的一部分,存放在栈帧中。如下图:
第一个问题: Java中的引用变量保存在内存中的哪块区域?是堆内存还是虚拟机栈的栈帧中?
要看是局部变量还是实例变量,局部变量(localVariable)存放在栈帧中,实例变量(instanceVariable)是它所属对象的一部分,存放在对象所在的堆内存区域中。
第二个问题:如何理解对象引用保存在栈中,对象保存在堆中这句话。
这句话本身不准确。“对象保存在堆中”绝对正确。 “对象的引用”要看是一个实例变量还是局部变量。见第一个问题答案。