JAVA中四种引用类型详解

一、引用类型(referenceObject)

概述:java从1.2版本把对象的引用分为四种级别,由高到低分别为:强引用、软引用、弱饮用、虚引用。

目的:使程序能更加灵活的控制对象的生命周期,更高效地利用 Heap。

1. 强引用(StrongReference)

最普遍使用的引用。一个具有强引用的对象,绝不会被垃圾回收器回收。当内存不足时,应用程序会抛出OutOfMemoryError错误,使程序异常终止,也不会回收具有强引用的对象。

2. 软引用(SoftReference)

如果一个对象只具有软引用,当内存足够时,程序不会回收软引用对象;当内存不足时,会回收这些软引用对象的内存。

3. 弱引用(WeakReference)

如果一个对象只具有弱引用,当垃圾回收器进行回收时,无论内存是否充足,都会回收这些弱引用对象的内存。

4. 虚引用(PhantemReference)

如果一个对象只具有虚引用,则和没有引用一样,在任何时候都可能被垃圾回收器回收。

二、可及性(reachability)

1. 五种可及性

对象的引用状态会影响对象的可及性,可及性可以分为五种:

strongly reachable

An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.

softly reachable

An object is softly reachable if it is not strongly reachable bu* can be reached by traversing a soft reference.

weakly reachable

An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.

phantom reachable

An object is phantom reachable, if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it

unreachable

An object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.

2. 判断

在很多时候,一个对象并不是从根集直接引用的,而是一个对象被其他对象引用,甚至同时被几个对象所引用,从而构成一个以根集为顶的树形结构。从根集到一个对象可以由很多条路径,由此带来了一个问题,那就是某个对象的可及性如何判断:

  • 单条引用路径可及性判断:在这条路径中,最弱的一个引用决定对象的可及性。
  • 多条引用路径可及性判断:几条路径中,最强的一条的引用决定对象的可及性。

三、使用方式

1. 强引用

对象申请内存空间时,默认已经是强引用了。

Object obj =new Object();  // 强引用

2. 软引用

使用SoftReference类,为对象添加一个软引用。使用get方法获取原有对象的引用,如果原有对象已经被回收,则返回null值。

Objecy obj = new Object();
SoftReference sfRefer = new SoftReference (obj);//为obj添加一个软引用
sfRefer.get();//获得原有对象引用

3. 弱引用

使用WeakReference类,为对象添加一个弱引用。使用方法和软引用类似。

Objecy obj = new Object();
WeakReference wfRefer = new WeakReference (obj);//为obj添加一个弱引用
wfRefer.get();//获得原有对象引用

4. 虚引用

使用PhantemReference类,为对象添加一个虚引用。必须与ReferenceQueue配合使用。不能通过PhantemReference获取原有对象引用,get方法永远返回null。

ReferenceQueue queue = new ReferenceQueue();
PhantomReference ref = new PhantomReference(new Object(), queue);

5. 引用队列(ReferenceQueue)

目的:监测引用的引用对象的回收情况,便于在对象被回收后进行进一步处理。

使用:和SoftReference、WeakReference、PhantemReference配合使用。如果引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个引用加入到与之关联的引用队列中。

Object object = new Object();
ReferenceQueue queue = new ReferenceQueue();
WeakReference wfRefer = new WeakReference(object, queue); //添加虚引用,并设置相关引用队列
object = null; //确保object只有一个虚引用

System.gc();  //触发垃圾回收,或者主动调用System.gc()
Thread.sleep(2000);

Reference ref = null; 
while((ref = queue.poll())!=null){
  if(ref == wfRefer){
    System.out.println("object has reclaimed"); //后续处理
  }
} 

四、Android环境的特殊性

google不建议在android环境中使用SoftReference

The lack of information on the value to your application of each reference limits the usefulness of soft references. References that are cleared too early cause unnecessary work; those that are cleared too late waste memory.

对于Android系统来说,对于内存较为敏感,对于内存释放也更加严格。 SoftReference 无法提供足够的信息可以让 系统很轻松地决定clear它还是keep它。

五、实际应用(Android)

1. 缓存

在应用开发过程中,有时候会经常访问数据缓存起来,减少读取数据的时间消耗,同时不希望这些数据影响到正常的内存回收。可以使用WeakRefercence来引用这些对象。可以使用WeakHashMap或者搭配LruCache使用。

2. Handler

为了避免Memory Leak,我们会定义一个内部静态类,然后以 WeakReference 的形式引用 Activity,使队列中的 Message (可能会排队很长时间)不会干扰到 Activity的正常回收。

public class MainActivity extends Activity {
    private static final int MSG_ID = 0x00;

    public void testSafeHandler() {
        SafeHandler handler = new SafeHandler(this);
        handler.sendEmptyMessage(MSG_ID);
    }

    public static class SafeHandler extends Handler {
        private WeakReference<Activity> mActivityRef;
        public SafeHandler(Activity activity) {
            mActivityRef = new WeakReference<>(activity);
        }

        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_ID:
                    Activity activity = mActivityRef.get();
                    if (activity != null) {
                        activity.finish();
                    }
            }
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容