Java对象引用是栈中存储的指向堆内存对象的逻辑地址,非对象本身;引用变量存于栈或堆,对象必在堆;GC依据可达性判断存活;分强、软、弱、虚四种引用类型;字符串字面量共享常量池对象。

Java中的对象引用,本质上是一个指向堆内存中对象的“指针”(但不是C/C++那种直接内存地址),它存储的是对象在堆中的逻辑地址(或句柄),用于访问该对象的实际数据。
对象引用不是对象本身
声明一个引用变量(如 String str;)时,JVM只在栈中分配一小块空间存放这个引用,此时它值为 null,并不创建任何对象。只有通过 new(或字符串常量池、反射等)真正创建对象后,引用才被赋予一个有效地址。
- String s1 = new String("hello"); → 在堆中新建一个String对象,“s1”这个变量保存的是该对象的引用值(比如0x1a2b3c)
- String s2 = s1; → 并非复制对象,只是把s1的引用值(0x1a2b3c)复制给s2,此时s1和s2指向同一个对象
- 修改对象内容(如通过可变对象的setter)会影响所有引用;但让某个引用指向新对象(s1 = new String("world");)不会影响s2
引用变量的生命周期与内存位置
引用变量本身存放在栈(局部变量)或方法区/堆(成员变量、静态变量)中,而它所指向的对象一定在堆内存中(包括数组、包装类、自定义类实例等)。垃圾回收器(GC)判断对象是否存活,依据正是“是否存在可达的引用链”,而非引用变量是否存在。
- 局部引用(如方法内定义的 List list = new ArrayList();)随方法调用结束从栈弹出,但只要list仍被其他活跃引用持有,其指向的ArrayList对象就不会被回收
- 成员变量引用(如 private Map cache;)随所属对象存于堆,其生命周期与宿主对象一致
- 将引用设为 null(list = null;)只是断开连接,有助于GC识别“不可达对象”,但不是强制立即回收
四种引用类型:决定GC行为的关键
Java提供强、软、弱、虚四种引用类(StrongReference、SoftReference、WeakReference、PhantomReference),它们的区别在于GC时对对象的“保留力度”不同:
立即学习“Java免费学习笔记(深入)”;
- 强引用:最常见(Object obj = new Object();),只要强引用存在,GC绝不回收
-
软引用:用 SoftReference
包装,内存不足时才被回收,适合做缓存(如图片缓存) -
弱引用:用 WeakReference
包装,GC每次运行都可能回收,常用于避免内存泄漏(如ThreadLocal、WeakHashMap的key) - 虚引用:必须配合引用队列(ReferenceQueue)使用,无法通过它获取对象实例,仅用于在对象被回收时收到通知(如堆外内存清理)
字符串常量池是理解引用共享的重要特例
字符串字面量("abc")会优先从字符串常量池查找复用,因此多个相同字面量可能共享同一引用:
- String a = "hello"; String b = "hello"; → a == b 为 true(指向常量池中同一个对象)
- String c = new String("hello"); → 在堆新建对象,c == a 为 false(但c.equals(a)为true)
- 常量池本身位于方法区(JDK 7+移到堆中),也是对象存储区域的一部分










