Android中深入学习对象的四种引用类型(强引用、软引用、弱引用、虚引用)

移动开发 Android
Java中,一切被视为对象,引用则是用来操纵对象的;在JDK1.2就把对象引用分为四种级别,从而使程序能更灵活控制它的生命周期,级别由高到底依次为:强 > 软 > 弱 > 虚引用。

[[429600]]

前言

Java中,一切被视为对象,引用则是用来操纵对象的;在JDK1.2就把对象引用分为四种级别,从而使程序能更灵活控制它的生命周期,级别由高到底依次为:强 > 软 > 弱 > 虚引用;而GC垃圾回收器(Garbage Collection)对不同的类型有着不同的处理方法,了解这些处理方式有助于我们写出更高质量的代码。

今天我们就来学习下:

一、引用详解

1、强引用 StrongReference

强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。如代码 String s=”abc” 中变量 s 就是字符串对象”abc” 的一个强引用。只要你给强引用对象 s 赋空值 null, 该对象就可以被垃圾回收器回收;因为该对象此时不再含有其他强引用;

  1. //str表示强引用,指向new String()这个对象 
  2. String str = new String(); 

2、弱引用

弱引用(WeakReference)是弱于软引用的引用类型,与软引用类似,不同的是弱引用不能阻止垃圾回收,在垃圾回收机制运行时,如果一个对象的引用是弱引用的话,不管内存空间是否足够,对象都会被回收。弱引用常常被用于防止内存泄漏,最常见的是单例和Handler造成的内存泄漏;

  1. //弱引用实例 
  2. WeakReference weakReference = new WeakReference<>(context); 
  3. //获取弱引用保存的引用 
  4. Context ctx = weakReference.get(); 

3、软引用

SoftReference:软引用–>当虚拟机内存不足时,将会回收它指向的对象;需要获取对象时,可以调用get方法;

软引用对象不会很快被jvm回收,jvm 会根据当前堆的使用情况来判断何时回收,当堆的使用频率接近阀值时才会被回收;

基本用法

  1. MySoftReference msf = new MySoftReference(); 
  2.   SoftReference sf = new SoftReference(msf); 
  3.   MySoftReference mySoftReference =(MySoftReference) sf.get(); 

基本特点

  • 如果内存足够,软引用是不会被jvm回收的;
  • 如果内存不够,会根据堆栈的使用情况来回收引用;
  • 未被回收的软引用是一直可被程序占有的;
  • 软引用可以和引用队列(ReferenceQueue)联合使用来实现内存紧张的高速缓存;
  • 如果软引用引用的对象被回收,Java虚拟机会把改软引用对象加到与之关联的引用队列中;
  1. ReferenceQueue rq = new ReferenceQueue(); 
  2.              SoftReference sf = new SoftReference(msf,rf); 

当软引用对象被回收后,ReferenceQueue队列中存储着强引用的Reference,然后可通过poll()来判断当前引用队列是否有失去软引用的对象,如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。可以检测出哪个软引用对象被回收,然后将其清除;

  1. Reference reference =null
  2.            while((reference==(EmployeeRef)rq.poll())){ 
  3.                    //清除操作 
  4.                    reference =null
  5.                     System.gc(); 
  6.                } 

4、虚引用

虚引用(PhantomReference)是最弱的引用,一个持有虚引用的对象和没有引用几乎是一样的,随时都可能被垃圾回收器回收。通过虚引用的get()方法获取到的引用都会失败(为null),虚引用必须和引用队列ReferenceQueue一起使用;

ReferenceQueue引用队列作用在于跟踪垃圾回收过程。当垃圾回收器回收对象时,如果发现它还有虚引用,就会在回收后销毁这个对象,并且将虚引用指向的对象加入到引用队列。只能通过虚引用是否被加入到ReferenceQueue来判断虚引用是否为GC回收,这也是判断对象是否为回收的唯一途径;

Java的Object类中有finalize()方法,原理:一旦垃圾回收器准备释放对象占用的内存空间,将首先调用finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存,但是问题在于,虚拟机不能保证finalize()何时被调用,因为GC运行时间不是固定的;

使用虚引用就能解决这个问题,虚引用主要用于跟踪垃圾被回收的活动,主要用来实现比较精细的内存使用控制,这对Android来说很有意义;

  1. //引用队列 
  2. ReferenceQueue queue = new ReferenceQueue<>(); 
  3. //虚引用 
  4. PhantomReference phantomReference = new PhantomReference(new Object(), queue); 
  5. Log.e(TAG, "虚引用:PhantomReference == " + phantomReference.get()); 
  6. //系统垃圾回收 
  7. System.gc(); 
  8. System.runFinalization(); 

phantomReference.get()获取的引用一直为null,调用系统回收垃圾,queue.poll()获取保存的引用对象,并且把它在这个队列中移除;

虚引用无法通过get()方法获取目标的引用,一直都是返回null,源码:

  1. public T get() { 
  2.     return null

总结

  • 强引用(StrongReference):不会自动回收,最难被GC回收的,宁可抛出异常也不回收强引用指向的对象;任何场景;
  • 软引用(SoftReference):内存不足时,GC会回收软引用指向的对象比较少使用,已被LruCache替代;
  • 弱引用(WeakReference):不管内存足不足,只要GC了都能回收弱引用指向的对象;常用于避免内存泄漏;
  • 虚引用(PhantomReference):随时都能回收,也称幽灵引用,相当于没有指向任何实例引用;跟踪对象是否被回收,很少使用。

本文转载自微信公众号「Android开发编程」

 

责任编辑:姜华 来源: Android开发编程
相关推荐

2020-12-02 09:01:40

Java基础

2013-08-19 17:14:04

.Net强引用弱引用

2009-06-19 16:19:23

Java对象引用

2019-10-24 07:42:28

Java引用GC

2013-09-16 16:48:50

Android优化软引用

2011-11-24 16:34:39

Java

2023-03-30 07:55:02

2015-11-02 17:20:00

Java弱引用

2009-09-11 11:09:36

C#引用类型

2016-09-18 19:07:33

Java值传递引用传递

2018-11-16 16:10:28

JavaOOM编程语言

2021-01-07 14:20:55

JavaGC

2020-11-10 08:45:35

Python

2022-03-08 13:06:25

引用队列jvm变量

2021-10-08 21:00:52

数据弱引用对象

2021-06-15 19:30:34

JAVA虚引用对象

2009-09-09 09:36:25

Linq对象引用

2009-08-14 17:09:48

C#引用类型

2022-01-02 06:55:08

Node.js ObjectWrapAddon

2010-07-20 13:53:44

Perl引用
点赞
收藏

51CTO技术栈公众号