有关“引用”、“对象”、“引用对象”的误解和看过源码说明后的理解

本文详细解析了Java中的引用类型,包括强引用、软引用、弱引用和虚引用的概念及应用场景,阐述了引用对象与引用状态,以及如何通过队列清除软引用和弱引用对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当看到

Object o = new Object();

有人说,“我们创建了一个名为 o 的对象。”
对吗?

大家常常这么说,可严格意义上并不正确。
正确的解读是:创建了一个引用 o 和一个 Object 对象,并把 o 指向(refer to)了这个 Object 对象(referent,所指之物)。

这个 o,我们称之为引用。
打印 o,会看到对象的地址,如 java.lang.Object@2530c12。
程序员操作 o,其实是通过地址去操作对象。
o 在栈上,对象在堆上。
这里的 o 是一个强引用,通过 “=”,赋值给引用的

引用

  • 强引用:指在程序代码之中普遍存在的,类似“Object obj=new Object()”这类的引用,只要强引用还存在,垃圾收集器永远不会回收掉被引用的对象实例。
  • 软引用:用来描述一些还有用但并非必需的对象。仅被软引用关联着的对象,在系统将要发生内存溢出异常之前,将会把这些对象实例列进回收范围之中进行回收。如果这次回收还没有足够的内存,才会抛出内存溢出异常。
  • 弱引用:用来描述非必需对象的,但是它的强度比软引用更弱一些,仅被弱引用关联的对象实例只能生存到下一次垃圾收集发生之前。当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象实例。
  • 虚引用:也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象实例是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是能在这个对象实例被收集器回收时收到一个系统通知。

对象

new Object();

在堆内存上,通过类 Object 的无参构造方法创建了一个 Object 对象。必须通过一个引用来操作它。
没有引用,下次垃圾收集器工作时,就会被清除。

引用对象

软引用是软引用,软引用对象是软引用对象。

Object o = new Object();
SoftReference<Object> softReference= new SoftReference(o)

有人说,softReference 是 o 的软引用。
对吗?

运行下面的代码:

Object o = new Object();
System.out.println(o);
SoftReference<Object> softReference= new SoftReference(o);
System.out.println(softReference);
o = null;
System.out.println(o);
System.out.println(softReference.get());

结果

java.lang.Object@2530c12
java.lang.ref.SoftReference@73c6c3b2
null
java.lang.Object@2530c12

所以上面的说法并不对,softReference 是创建的 SoftReference 对象的强引用。
这个 SoftReference 对象里面,含有软引用的逻辑。

可以理解为,栈里的 softReference 指向了堆内的 SoftReference 对象,堆内的 SoftReference 对象软指向了 Object 对象。

类 Reference<T> 是所有引用对象的抽象基类。

状态

一个 Reference 实例一定处在于 4 种可能的内在状态之一。

  • Active(激活):受垃圾收集器的特殊处理。某些时候,垃圾收集器检测到对象的可达性改变到适当的状态之后,它将实例的状态更改为 Pending (待定)或 Inactive(闲置)状态,这取决于该实例是否和队列一起创建。
    在这里插入图片描述
    如果按情况2创建的实例,它还将实例添加到 pending-Reference 列表。新创建的实例是 active 的。

  • Pending(待定):由 Reference-handler 线程加入 pending-Reference 列表。按情况1创建的实例不会进入这个状态。

  • Enqueued(加入了队列):加入到了 ReferenceQueue。如果从 ReferenceQueue 中移除,会进入 Inactive 状态。按情况1创建的实例不会进入这个状态。

  • Inactive(闲置):无事可做。一旦进入 Inactive 状态,不会再改变。

方法

get

返回堆上的对象。
如果 Reference<T> 在堆上的对象被程序或者垃圾收集器清除了,它会返回 null。

public T get() {
   return this.referent;
}

子类

SoftReference<T> 软引用对象

软引用指向的对象在垃圾收集器自我判定需要内存的时候被清除。

软引用对象通常用于内存敏感的缓存,如图像缓存。

如果垃圾收集器某时判定对象软可达(没有强引用,有软引用)的,它可能会清除那个对象所有的软引用,和任何其它通过强引用链引用(如,被一个强可达的容器包含)的软可达对象的软引用。(一旦发现某个对象软可达,可能清除所有对象的软引用)

同时,或一会儿后,它会将新被清除的软引用对象放入队列(如果有)。

在虚拟机抛出 OutOfMemoryError 异常前,会清除所有的软引用指向的对象

只要软引用的对象是强可达的,软引用就不会被清除。

可以通过队列清除软引用对象

WeakReference<T> 弱引用对象

假如垃圾收集器在某时判定对象是弱可达(没有强引用和软引用,有弱引用)的,它会清除那个对象所有的弱引用,和任何其它通过强/软引用链引用的弱可达对象的弱引用。(一旦发现某个对象弱可达,清除所有对象的弱引用)

同时,它会声明所有的弱可达对象 finalizable(可终结,可回收)。

同时,或一会儿后,它会将新被清除的弱引用对象放入队列(如果有)。

可以通过队列清除弱引用对象

PhantomReference<T> 虚引用对象

虚引用对象在垃圾收集器判定虚引用所指向的对象可能(may otherwise)被回收后,放入队列。(必须有队列)

假如垃圾收集器在某时判定对象是弱可达(没有强引用、软引用和弱引用,只有虚引用)的,同时,或一会儿后,它会将虚引用对象放入队列。

不像软引用对象和弱引用对象,虚引用对象在入队列后不会被垃圾回收器自动清除。

 public T get() {
        return null;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值