Java 对象的强引用、软引用、弱引用和虚引用

以下内容部分来自 疯狂Java讲义/李刚 ,博客仅用于个人笔记及帮助他人用途,无任何商业目的,如有侵权,请联系作者删除。

对大部分对象而言,程序里会有一个引用变量引用该对象,这是最常见的引用方式。除此之外, java.lang.ref 包下提供了 3 个类: SoftReference、PhantomReference 和 WeakReference,它们分别代表了系统对对象的 3 种引用方式:软引用、虚引用和弱引用。因此,Java 语言对对象的引用有如下 4 种方式:

  1. 强引用(StrongReference)
    这是 Java 程序中最常见的引用方式。程序创建一个对象,并把这个对象赋给一个引用变量,程序通过该引用变量来操作实际的对象,前面介绍的对象和数组都采用了这种强引用的方式。当一个对象被一个或一个以上的引用变量所引用时,它处于可达状态,不可能被系统垃圾回收机制回收。

  2. 软引用(SoftReference)
    软引用需要通过 SoftReference 类来实现,当一个对象只有软引用时,它有可能被垃圾回收机制回收。对于只有软引用的对象而言,当系统内存空间足够时,它不会被系统回收,程序也可以使用该对象;当系统内存空间不足时,系统可能会回收它。软引用通常用于对内存敏感的程序中。

  3. 弱引用(WeakReference)
    弱引用通过WeakReference 类来实现,弱引用和软引用很想,但弱引用的引用级别更低。对于只有弱引用的对象而言。当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。当然,并不是说当一个对象只有弱引用时,它就会立即被回收——正如那些失去引用的对象一样,必须等到系统垃圾回收机制运行时才会被回收。

  4. 虚引用(PhantomReference)
    虚引用通过 PhantomReference 类实现,虚引用完全类似于没有引用。虚引用对对象本身没有太大影响,对象甚至感觉不到虚引用的存在。如果一个对象只有一个虚引用时,那么它和没有引用的效果大致相同。虚引用主要用于跟踪对象被垃圾回收的状态,虚引用不能单独使用,虚引用必须和引用队列(ReferenceQueue)联合使用。

上面三个引用类都包含了一个 get 方法,用于获取被它们所引用的对象。

引用队列由 java.lang.ref.ReferenceQueue 类表示,它用于保存被回收后对象的引用。当联合使用软引用、弱引用和引用队列时,系统在回收被引用的对象之后,将把被回收对象对应的引用添加到关联的引用队列中,与软引用和弱引用不同的是,虚引用在对象被释放之前,将把它对应的虚引用添加到它关联的引用队列中,这使得可以在对象被回收前采取行动。

软引用和弱引用可以单独使用,但虚引用不能单独使用,单独使用没有太大的意义。虚引用的主要作用就是跟踪对象被垃圾回收的状态,程序可以通过检查与虚引用关联的引用队列中时候已经包含了该虚引用,从而了解虚引用所引用的对象是否即将被回收。

下面程序示范了弱引用所引用的对象被系统垃圾回收的过程
ReferenceTest.java

import java.lang.ref.*;
public class ReferenceTest{
  public static void main(String[] args){
    //创建一个字符串对象
    String str = new String("Test");
   //创建一个弱引用,让此弱引用引用到上面的字符串
    WeakReference wr = new WeakReference(str);
    //切断 str 和 "Test" 字符串的引用
    str = null;
    //取出弱引用所引用的对象
    System.out.println(wr.get());
    //强制垃圾回收
    System.gc();
    System.runFinalization();
    //再次取出弱引用所引用的对象
    System.out.println(wr.get());
  }
}

使用这些引用类可以避免在程序执行期间将对象保留在内存中。如果以软引用、弱引用或虚引用的方式引用对象,垃圾收集器就能随意释放对象。如果希望尽可能减小程序在其生命周期中所占的内存大小时,这些引用类就很有用处。
必须指出:要使用这些特殊的引用类,就不能保留对对象的强引用;如果保留了对对象的强引用,就会浪费这些引用类所提供的任何好处。

猜你喜欢

转载自blog.csdn.net/u013872857/article/details/50570372