Android中深入学习对象的四种引用类型

目录
  • 一、引用详解
    • 1、强引用 StrongReference
    • 2、弱引用
    • 3、软引用
    • 4、虚引用

前言:

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

一、引用详解

1、强引用 StrongReference

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

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

2、弱引用

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

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

3、软引用

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

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

基本用法:

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

基本特点:

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

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

Reference reference =null;
           while((reference==(EmployeeRef)rq.poll())){
                   //清除操作
                   reference =null;
                    System.gc();
               }

4、虚引用

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

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

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

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

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

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

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

public T get() {
    return null;
}

总结:

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

到此这篇关于Android中深入学习对象的四种引用类型的文章就介绍到这了,更多相关Android中深入学习对象引用类型内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android中将Bitmap对象以PNG格式保存在内部存储中的方法

    在Android中进行图像处理的任务时,有时我们希望将处理后的结果以图像文件的格式保存在内部存储空间中,本文以此为目的,介绍将Bitmap对象的数据以PNG格式保存下来的方法. 1.添加权限 由于是对SD card进行操作,必不可少的就是为你的程序添加读写权限,需要添加的内容如下: <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

  • Android使用Canvas对象实现刮刮乐效果

    在淘宝.京东等电商举办活动的时候,经常可以看到在移动客户端推出的各种刮奖活动,而这种活动也受到了很多人的喜爱.从客户端的体验来说,这种效果应该是通过网页来实现的,那么,我们使用Android的自带控件能不能实现这种刮刮乐的效果呢?当然可以,本篇文章将介绍使用Canvas这个对象,如何实现"刮刮乐"的效果. 先看效果图 下面我们看一下如何使用代码实现 布局文件 <FrameLayout xmlns:android="http://schemas.android.com/a

  • Android使用FontMetrics对象计算位置坐标

    Canvas绘制文本时,使用FontMetrics对象,计算位置的坐标. public static class FontMetrics { /** * The maximum distance above the baseline for the tallest glyph in * the font at a given text size. */ public float top; /** * The recommended distance above the baseline for

  • Android List(集合)中的对象以某一个字段排序案例

    在Android开发中,有时我们需要对一个对象的集合按照某一个字段进行排序, Bean public class Student { private int studentId; private String studentName; private int age; public Student(int studentId , String studentName, int age){ this.studentId=studentId; this.studentName=studentName

  • Android中传递对象的三种方法的实现

    Android中,Activity和Fragment之间传递对象,可以通过将对象序列化并存入Bundle或者Intent中进行传递,也可以将对象转化为JSON字符串,进行传递. 序列化对象可以使用Java的Serializable的接口.Parcelable接口.转化成JSON字符串,可以使用Gson等库. 1.Serializable public class Author implements Serializable{ private int id; private String name

  • Android中实现长按修改ListView对象的内容

    实现的效果如下: 我在ListView的Item长按事件内打开一个弹出窗口,窗口内有一个EditText对象,在这个编辑框内输入文本点确定后,直接修改掉ListView对象内某个TextView对象的内容. 示例代码如下: import android.os.Bundle; import android.app.Activity; import android.app.AlertDialog; import android.graphics.Color; import android.view.

  • Android编程实现全局获取Context及使用Intent传递对象的方法详解

    本文实例讲述了Android编程实现全局获取Context及使用Intent传递对象的方法.分享给大家供大家参考,具体如下: 一.全局获取 Context Android 开发中很多地方需要用到 Context,比如弹出 Toast.启动活动.发送广播.操作数据库-- 由于很多操作都是在活动中进行的,而活动本身就是一个 Context 对象,所以获取 Context 并不是那么困难. 但是,当应用程序的架构逐渐开始复杂起来的时候,很多的逻辑代码都将脱离 Activity 类,由此在某些情况下,获

  • Android中利用C++处理Bitmap对象的实现方法

    相信有些Android&图像算法开发者和我一样,遇到过这样的状况:要对Bitmap对象做一些密集计算(例如逐像素的滤波),但是在java层写循环代码来逐像素操作明显是不现实的,因为Java代码的运行速度太慢,而一副很小的240*320图像就有76800个像素,如果考虑到RGB三通道(或者ARGB四通道),还要对这个数量乘以3/4.因此对图像的密集计算一般都利用Jni接口,用C++实现.那么问题来了,怎么把Bitmap中的像素数据从Java层传到C++层? 做法1:之前的做法 我之前的做法是这样的

  • Android中深入学习对象的四种引用类型

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

  • Android中Intent传递对象的两种方法Serializable,Parcelable

    Android中的传递有两个方法,一个是Serializable,另一个是Parcelable. Serializable是J2SE本身就支持的.而Parcelable是Android所特有的. 二者的使用场景和区别: 1)在使用内存的时候,Parcelable比Serializable性能高,所以推荐使用Parcelable. 2)Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC. 3)Parcelable不能使用在要将数据存储在磁盘上的情况,因为Parcelab

  • Android中Intent传递对象的3种方式详解

    前言 相信Intent的用法大家已经比较熟悉了,Intent可以用来启动Activity,Service等等,同时我们也可以通过Intent来进行传递数据,当我们使用Intent在Activity 间传递信息时发现putExtra() 方法并不支持自定义对象的传输,下面就来介绍三种解决方式. 一.Serializable 方式 这是最简单的一种方法,因为我们要做的就是让我们自定义的对象实现 Serializable 这个空接口. public class Person implements Se

  • Android编程实现获取图片资源的四种方法

    本文实例讲述了Android编程实现获取图片资源的四种方法.分享给大家供大家参考,具体如下: 1. 图片放在sdcard中: 复制代码 代码如下: Bitmap imageBitmap = BitmapFactory.decodeFile(path)//path 是图片的路径,跟目录是/sdcard 2. 图片在项目的res文件夹下面 //得到application对象 ApplicationInfo appInfo = getApplicationInfo(); //得到该图片的id(name

  • android中Webview实现截屏三种方式小结

    本人最近学习了android中Webview实现截屏三种方式,下面我来记录一下,有需要了解的朋友可参考.希望此文章对各位有所帮助. 第一种方式 通过调用webview.capturePicture(),得到一个picture对象,根据图像的宽和高创建一个Bitmap,再创建一个canvas,绑定bitmap,最后用picture去绘制. //获取Picture对象 Picture picture = wv_capture.capturePicture(); //得到图片的宽和高(没有reflec

  • android实现线程间通信的四种常见方式

    1,通过Handler机制 主线程中定义Handler,子线程发消息,通知Handler完成UI更新,Handler对象必须定义在主线程中,如果是多个类直接互相调用,就不是很方便,需要传递content对象或通过接口调用. 另外Handler机制与Activity生命周期不一致的原因,容易导致内存泄漏,不推荐使用. private void one() { handler=new Handler(){ @Override public void handleMessage(Message msg

  • Android中实现多线程操作的几种方式

    目录 前言 最基础的方式 继承Thread类并实现run()方法 匿名内部类 实现Runnable接口 callable+FutureTask 线程池 手动创建线程池 使用Executors创建线程池 Android中特有的实现多线程 使用HandlerThread 使用IntentService JobIntentService/JobScheduler WorkManager WorkManager 使用协程 AsyncTask 结语 前言 多线程一直是一个老大难的问题,首先因为它难以理解,

  • 比较JavaScript对象的四种方式

    目录 前言 引用比较 手动比较 浅层比较 深层比较 总结 前言 比较JavaScript中的原始值非常简单.只需使用任何一种可用的相等运算符即可,例如严格相等运算符: 'a' === 'c'; // => false 1 === 1; // => true 但是对象却有结构化数据,所以比较起来比较困难.在本文中,你将学习如何正确比较JavaScript中的对象. 引用比较 JavaScript 提供了 3 种对值进行比较的方法: 严格相等运算符=== 宽松相等运算符== Object.is()

  • JavaScript 对象的四种方式比较详解

    目录 前言 1. 引用比较 2. 手动比较 3. 浅层比较 4. 深层比较 5. 总结 前言 比较 JavaScript 中的值非常简单,只需用相等运算符即可,例如严格相等运算符: 'a' === 'c'; // => false 1 === 1; // => true 但是对象却有结构化的数据,所以比较起来比较困难.在本文中,你将学习如何正确比较 JavaScript 中的对象. 1. 引用比较 JavaScript 提供了 3 种方法来对值进行比较: 严格相等运算符 === 宽松相等运算符

  • JavaScript对象的四种创建方法

    目录 前言 1. 基于对象字面量 2. 利用new Object方式创建对象 3. 基于构造函数 4. 基于工厂方法 前言 今天我们来学习一下JavaScript中关于对象的四种创建方法. 首先,我们来确定一个对象的属性和方法.比如说,我们想要我们定义一个girlFriend的对象,希望她有名字name.年龄age的属性,希望有一个getName方法,来获取名字:最后属性是一个稍微复杂的对象属性address,它具有两个属性值,所在地name和邮政编码code. 接下来,我们来通过本篇内容,来看

随机推荐