java 中的引用类型

1、强引用类型

2、弱引用

3、软引用

我们来举例说明下

package www.weiyuan.test;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub

//创建了一个强引用类型 String str = "abc"; //创建一个软引用对象 SoftReference<String> sfr = new SoftReference<String>(str); //创建一个弱引用类型 WeakReference<String> wrf = new WeakReference<String>(str); } }

对象的可及性:一个对象可由多个变量来来引用,对象的可及性由最强引用类型来决定

 上面对象adc有三个引用,一个是强可及,一个是软可及,还有一个是弱可及,最强引用是强可及

强可及对象永远不会被gcc垃圾回收器回收

软可及对象当系统内存不足的时候,gcc会把软可及对象回收掉

弱可及对象当gcc发现这个对象是弱可及对象就马上将对象回收

package www.weiyuan.test;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         String str = "abc";
       //创建一个软引用对象
         SoftReference<String> sfr = new SoftReference<String>(str);
         //创建一个弱引用类型
         WeakReference<String> wrf = new WeakReference<String>(str);
         //去除强可及str对象不再和adc对象存在任何关系
         str = null;
         //通过软可及获得对象的值
         String result1 = sfr.get();
         //通过弱可及获得对象的值
         String result2 = wrf.get();
         System.out.println("result1 ="+result1);
         System.out.println("result2 ="+result1);
    }

}

输出的结果是:

result1 =abc
result2 =abc

str = null;就是去掉str和对象"abc"的强可及关系,此时依然可以通过软引用和弱引用获得对象所关联的值

弱可及对象当gcc发现这个对象是弱可及对象就马上将对象回收

package www.weiyuan.test;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         String str = "abc";
       //创建一个软引用对象
         SoftReference<String> sfr = new SoftReference<String>(str);
         //创建一个弱引用类型
         WeakReference<String> wrf = new WeakReference<String>(str);
         //去除强可及str对象不再和adc对象存在任何关系
         str = null;
         //清除软引用的引用链
         sfr.clear();
         //通过弱可及获得对象的值
         String result2 = wrf.get();
         //通过软可及获得对象的值
         String result1 = sfr.get();
        
         System.out.println("result1 ="+result1);
         System.out.println("result2 ="+result2);
    }

}

我们使用

        sfr.clear();去掉对象的软引用链接,这个时候对象的可及性是弱引用对象,清除之后通过软引用我们无法获得对象的值,但是依然可以通过弱引用获得对象的值,我们来看日志的打印输出

result1 =null
result2 =abc

在上面代码的基础上,我们知道当前对象的可及性是弱引用,我们收到调用gcc回收,看能否在获得对象的值

package www.weiyuan.test;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         String str = "abc";
       //创建一个软引用对象
         SoftReference<String> sfr = new SoftReference<String>(str);
         //创建一个弱引用类型
         WeakReference<String> wrf = new WeakReference<String>(str);
         //去除强可及str对象不再和adc对象存在任何关系
         str = null;
         //清除软引用的引用链
         sfr.clear();
         //运行垃圾回收器
         System.gc();
         //通过弱可及获得对象的值
         String result2 = wrf.get();
         //通过软可及获得对象的值
         String result1 = sfr.get();
        
         System.out.println("result1 ="+result1);
         System.out.println("result2 ="+result2);
    }

}

该对象已经是弱引用了,我们调用了系统的垃圾回收器,发现对象如果是弱引用,就立刻回收该对象的值

我们来看看日志的打印

result1 =null
result2 =abc

居然在垃圾回收器之后,居然还可以通过弱引用获得对象的值

这是为啥了,这里因为埋了一个坑

因为创建的对象

 "abc"是存在在系统的常量池中的,我们使用gc是无法回收常量池中的对象的,gc只能回收堆内存中的弱引用对象
我们把
package www.weiyuan.test;

import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         String str = new String("abc");
       //创建一个软引用对象
         SoftReference<String> sfr = new SoftReference<String>(str);
         //创建一个弱引用类型
         WeakReference<String> wrf = new WeakReference<String>(str);
         //去除强可及str对象不再和adc对象存在任何关系
         str = null;
         //清除软引用的引用链
         sfr.clear();
         //运行垃圾回收器
         System.gc();
         //通过弱可及获得对象的值
         String result2 = wrf.get();
         //通过软可及获得对象的值
         String result1 = sfr.get();
        
         System.out.println("result1 ="+result1);
         System.out.println("result2 ="+result2);
    }

}
我们运行下代码:

result1 =null
result2 =null

通过new String的对象都是存在在堆内存中,所以我们使用gc就能够回收了。



原文地址:https://www.cnblogs.com/kebibuluan/p/7210763.html