zoukankan      html  css  js  c++  java
  • Java 引用分类:StrongReference、SoftReference、WeakReference、PhantomReference

    一,定义

    在Java中,引用的定义是:如果reference类型的数据中存储的数值代表的是另一块内存的起始地址,就称这块内存代表着一个引用。后面在JDK1.2开始,引用的概念被扩充,引用被分为强引用(StrongReference)、软引用(SoftReference)弱引用、(WeakReference)、虚引用(PhantomReference)。这四种引用的强度关系:强引用>软引用>弱引用>虚引用。

    1,强引用:这种引用就是我们在代码中最常用的,类似于“Object o = new Object()”,这个“o”引用就是强引用,只要强引用还存在,GC永远不会回收掉被引用的对象。 
    2,软引用:软引用是用来描述那些有用但非必须的对象,在系统发生内存溢出之前会对这些对象进行回收,也就是说内存不足就会回收这些对象,如果内存足够,即使手动GC也不会回收被软件引用指向的对象。 
    3,弱引用:弱引用用来描述非必须对象,强度比软引用更弱,当GC工作时,不管当前内存是否足够,都会回收只被弱引用指向的对象。 
    4,虚引用:与其他几种引用不同,虚引用不会影响对象的生存时间,也不能通过虚引用来获得一个对象的实例,它唯一的目的就是对象被回收时能收到一个通知。

    二,实例说明

    说了几种引用的概念,我们结合一些实例来说明他们各自的特性。

    public class MyClass {
        public static void main(String[] agrs){
            MyClass myClass = new MyClass(20,"Zhang san");
            SoftReference<MyClass> softReference = new SoftReference<MyClass>(new MyClass(15,"Li si"));
            WeakReference<MyClass> weakReference = new WeakReference<MyClass>(new MyClass(10,"Wang er"));
            PhantomReference<MyClass> phantomReference = new PhantomReference<>(new MyClass(5,"Ma zi"), new ReferenceQueue<>());
    
            System.out.println("strong reference myClass = " + myClass);
            System.out.println("soft reference get: " + softReference.get());
            System.out.println("weak reference get: " + weakReference.get());
            System.out.println("phantom reference get: " + phantomReference.get());
    
        }
    
        private int age;
        private String name;
    
        public MyClass(int age, String name){
            this.age = age;
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "name[" + this.name + "] age[" + this.age + "]";
        }
    
        @Override
        protected void finalize() throws Throwable {
            super.finalize();
            System.out.println("finalize method executed...." + this);
        }
    }

    我们先看上面的例子,一个测试类,main()方法中定义了四个变量,分别是强引用、软引用、弱引用、虚引用,我们看下运行后的打印信息

    strong reference myClass = name[Zhang san] age[20]
    soft reference get: name[Li si] age[15]
    weak reference get: name[Zhang san] age[20]
    phantom reference get: null

    从打印信息我们可以得知,虚引用虽然指向了一个对象,但是通过该引用得到的对象是null,这就验证了前面我们说的,不能通过虚引用得到对象的实例。 
    接下来,我们做点修改,加上显示调用垃圾回收,主要修改如下:

    public static void main(String[] agrs){
        MyClass myClass = new MyClass(20,"Zhang san");
        SoftReference<MyClass> softReference = new SoftReference<MyClass>(new MyClass(15,"Li si"));
        WeakReference<MyClass> weakReference = new WeakReference<MyClass>(new MyClass(10,"Wang er"));
        PhantomReference<MyClass> phantomReference = new PhantomReference<>(new MyClass(5,"Ma zi"), new ReferenceQueue<>());
    
        System.gc();
        System.out.println("strong reference myClass = " + myClass);
        System.out.println("soft reference get: " + softReference.get());
        System.out.println("weak reference get: " + weakReference.get());
        System.out.println("phantom reference get: " + phantomReference.get());
    
    }

    运行结果如下:

    strong reference myClass = name[Zhang san] age[20]
    finalize method executed....name[Ma zi] age[5]
    finalize method executed....name[Wang er] age[10]
    soft reference get: name[Li si] age[15]
    weak reference get: null
    phantom reference get: null

    从结果中我们可以看到,当显示调用垃圾回收时,弱引用和虚引用对象都被回收了,这说明弱引用和虚引用指向的对象在发生GC时一定会被回收。但强引用和软引用指向的对象并没有被回收。我们接着做些修改,修改如下:

    public static void main(String[] agrs){
        MyClass myClass = new MyClass(20,"Zhang san");
        SoftReference<MyClass> softReference = new SoftReference<MyClass>(new MyClass(15,"Li si"));
        WeakReference<MyClass> weakReference = new WeakReference<MyClass>(new MyClass(10,"Wang er"));
        PhantomReference<MyClass> phantomReference = new PhantomReference<>(new MyClass(5,"Ma zi"), new ReferenceQueue<>());
        myClass = null;
        System.gc();
        System.out.println("strong reference myClass = " + myClass);
        System.out.println("soft reference get: " + softReference.get());
        System.out.println("weak reference get: " + weakReference.get());
        System.out.println("phantom reference get: " + phantomReference.get());
    
    }

    同样看下运行的结果

    strong reference myClass = null
    finalize method executed....name[Zhang san] age[20]
    finalize method executed....name[Ma zi] age[5]
    finalize method executed....name[Wang er] age[10]
    soft reference get: name[Li si] age[15]
    weak reference get: null
    phantom reference get: null

    可以看出这个时候,强引用指向的对象被回收了,这是因为我们把myClass引用置空了,也就是说name为张三,age为20的对象没被引用了,当发生GC的时候,该对象就会被回收。

    三,总结

    强引用指向的对象如果被引用,发生GC时是不会被回收的,除非该对象没有被引用;软引用指向的对象在发生GC时不一定会被回收,该对象会被回收的条件是内存不足;弱引用和虚引用指向的对象在发生GC时一定会被回收,此外通过虚引用得不到引用的对象实例。

  • 相关阅读:
    缓存小记
    ffplay源码分析(转)
    (转)Qt之QNetworkProxy(网络代理)
    pcm编码为aac后播放变快且模糊
    Qt常用控件(转)
    Qml(二)Quick基本组件
    QML(一)HelloWorld
    C++ MySQL连接及增删改查操作
    Linux ar打包静态库 plugin needed to handle lto object 问题
    Qt笔记(二)linux下Qt安装使用
  • 原文地址:https://www.cnblogs.com/printN/p/6204172.html
Copyright © 2011-2022 走看看