在Java中,“引用”起着非常重要的作用,尤其是在垃圾回收机制中,引用决定了对象会不会被回收。引用可以分为“强、软、弱、虚”四种类型,概括的来说:
强引用,就是普通的对象引用关系
软引用,用于维护一些可有可无的对象。只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。
弱引用,拥有更短的生命周期,当 JVM 进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。
虚引用是一种形同虚设的引用,在现实场景中用的不是很多,主要用来跟踪对象被垃圾回收的活动。
一 强引用
强引用是最常见的引用方式,我们使用的大多数引用都是强引用,如我们使用new
关键字创建对象时,如果使用赋值语句将对象赋给一个变量,这个变量就持有该对象的强引用。只要强引用存在,垃圾回收器就不会回收该对象。即使内存空间不足,虚拟机也不会轻易回收有强引用关系的对象,而是会抛出OOM异常。
Object obj = new Object(); // 创建对象并持有强引用
当一个对象上不再存在强引用关系时,它就会被作为垃圾回收掉,我们也可以显示地将引用赋值为null,以中断强引用和某个对象之间的关联。
二 软引用
软引用用于维护一些可有可无的对象,如果内存不足,虚拟机就会回收这些对象以释放内存空间,但内存充足的情况下,虚拟机不会回收它们。我们可以使用SoftReference关键字来创建软引用。
SoftReference<Object> softRef = new SoftReference<>(new Object()); // 创建软引用
由于软引用的特性,它经常会被运用于实现缓存的场景,如浏览器的后退按钮,这个后退时显示的网页内容可以重新进行请求或者从缓存中取出。
三 弱引用
弱引用会比软引用更加弱一些,它会在虚拟机进行垃圾回收时直接被回收掉,无论内存是否充足。使用WeakReference来创建。
WeakReference<Object> weakRef = new WeakReference<>(new Object()); // 创建弱引用
弱引用可以和引用队列联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。
Object o = new Object(); //只要o还指向对象就不会被回收
WeakReference<Object> wr = new WeakReference<Object>(o);
当要获得weak reference引用的object时, 首先需要判断它是否已经被回收,如果wr.get()方法为空, 那么说明weakCar指向的对象已经被回收了。
弱引用可以用在实现对对象的辅助引用情况下,比如在WeakHashMap中使用弱引用作为键值。此外,如果想引用一个对象,但是这个对象有自己的生命周期,我们又不想介入这个对象的生命周期,这时候就可以使用弱引用。
四 虚引用
虚引用是所有引用类型中最弱的一种。它的存在几乎没有意义,因为无法通过虚引用获取对象。虚引用主要用于跟踪对象被垃圾回收的状态。使用PhantomReference关键字创建。
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue); // 创建虚引用
虚引用的构造函数需要与一个引用队列(ReferenceQueue)一起使用。当虚引用指向的对象被垃圾回收时,将会被放入引用队列中,通过引用队列可以得知对象已经被回收。