Java四种引用-Android面试准备2019-1-22

四种引用

1.强引用(StrongReference)

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

2.软引用(SoftReference)

软引用需要通过SoftReference类来实现。对于只有软引用的对象而言,当系统内存空间足够时,它不会被系统回收;当系统内存空间不足时,系统可能会回收它。软引用通常用于对内存敏感的程序中。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。

软引用示例(get()方法用来获取当前引用所指向的对象)

3.弱引用(WeakReference)

弱引用通过WeakReference类实现。对于只有弱引用的对象而言,当系统垃圾回收机制运行时,不管系统内存是否足够,都会回收该对象所占用的内存。当然,并不是说当一个对象只有弱引用时就会立即被回收,而是等到系统垃圾回收机制运行时才会被回收。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被JVM回收,这个软引用就会被加入到与之关联的引用队列中。(用法同软引用,改为WeakReference即可)

Java四种引用-Android面试准备2019-1-22_第1张图片
弱引用举例
Java四种引用-Android面试准备2019-1-22_第2张图片
第9行后内存状况

第5行当使用new String("Effective Java")时,JVM会先使用常量池来管理"Effective Java"直接量,再调用String类的构造器来创建一个新的String对象,新创建的String对象被保存在堆内存中,所以可以被14与15行的回收代码进行回收。程序运行结果为Effective Java\nnull。

若使用第6行,当Java程序直接使用形如"Effective Java"的字符串直接量时,JVM将会使用常量池来管理这些字符串,所以不能被垃圾回收机制回收。程序运行结果为Effective Java\nEffective Java。

4.虚引用(Phantom Reference)

虚引用通过PhantomReference类实现。虚引用完全类似于没有引用。如果一个对象与虚引用关联,则跟没有引用与之关联一样,在任何时候都可能被垃圾回收器回收,也无法通过虚引用来获取一个对象的实例。虚引用主要用于跟踪对象被垃圾回收的状态,为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知。虚引用不能单独使用,虚引用必须和引用队列(Reference Queue)联合使用,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

Java四种引用-Android面试准备2019-1-22_第3张图片
虚引用举例

以上四种引用的引用强度依次递减。

Java四种引用-Android面试准备2019-1-22_第4张图片
总结

软、弱引用中取出被引用对象

由于垃圾回收的不确定性,当程序希望从软、弱引用中取出被引用对象时,可能这个被引用对象已经被释放了。如果程序需要使用那个被引用的对象,则必须重新创建该对象。下面代码显示了这个过程。

Java四种引用-Android面试准备2019-1-22_第5张图片
取出被引用对象示例

引用队列

引用队列由java.lang.ref.ReferenceQueue类表示,它用于保存被回收后对象的引用。当联合使用软引用、弱引用和引用队列时,系统在回收被引用的对象之后,将把被回收对象对应的引用添加到关联的引用队列中。与软引用和弱引用不同的是,虚引用在对象被释放之前,将把它对应的虚引用添加到它关联的引用队列中,这使得可以在对象被回收之前采取行动。软引用和弱引用可以单独使用,但虚引用不能单独使用,单独使用虚引用没有太大的意义。虚引用的主要作用就是跟踪对象被垃圾回收的状态,程序可以通过检査与虚引用关联的引用队列中是否已经包含了该虚引用,从而了解虚引用所引用的对象是否即将被回收。

你可能感兴趣的:(Java四种引用-Android面试准备2019-1-22)