java中的引用类型

Java中的引用类型

首先java中的引用类型有如下几种:强引用,软引用,弱引用,虚引用。
接下来会结合代码尝试着对这几种引用类型做下讲解。

测试四种引用类型

首先,我们创建了这样一个类:

public class Test1 {
    @Override
    protected void finalize()throws Throwable{
        System.out.println("finalize发生	");
    }
}

重写了finalize方法 这样在Test1垃圾回收时会调用这个方法

强引用

我们平时使用的new对象的形式就是强引用

public class main {
    public static void main(String[] args) {
        Test1 t1 = new Test1();
        t1 = null;
        System.gc();
        System.out.println("t1 = " + t1);
    }
}

结果:
在这里插入图片描述
仅当对象不被引用指向时,对象被当作垃圾清空,触发finalize方法。

软引用
public class Test2 {
    public static void main(String[] args) {
        SoftReference<byte[]> test = new SoftReference<>(new byte[1024*1024*15]);
        System.out.println("第一次调用" + test.get());
        System.gc();
        
        try{
            Thread.sleep(500);
        }catch (Exception ee){
            ee.printStackTrace();
        }
        
        System.out.println("第二次调用" + test.get());
        byte[] test2 = new byte[1024*1024*20];
        System.out.println("第三次调用" + test.get());

    }
}

我们在运行这个程序之前先在VM option中输入参数“-Xmx30M”,意思是设置堆的最大内存为30M

结果:
在这里插入图片描述
此时我们发现 前面两次调用都成功了,但是最后一次没有成功。这样的原因是,软引用会在内存发生溢出之前,它就会被回收,所以软引用很适合作为缓存使用。

弱引用
import java.lang.ref.WeakReference;

public class Test3 {
    public static void main(String[] args) {
        WeakReference<Test1> w = new WeakReference<>(new Test1());

        System.out.println("第一次调用:" + w.get());
        System.gc();
        System.out.println("第二次调用:" + w.get());
    }
}

结果:
在这里插入图片描述
我们能够发现,一旦经过一次gc,那么弱引用就会被清理。

虚引用

一般我们不会使用虚引用,运行时设置参数“-Xmx20M”.

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.LinkedList;
import java.util.List;

public class Test4 {
    private static final List<Object> List = new LinkedList<>();
    private static final ReferenceQueue<Test1> QUEUE = new ReferenceQueue<>();

    public static void main(String[] args) {
        PhantomReference<Test1> phantomReference = new PhantomReference<>(new Test1(),QUEUE);

        System.out.println(phantomReference.get());

        new Thread(() -> {
            while(true){
                List.add(new byte[1024*1024]);
                try{
                    Thread.sleep(1000);

                }catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
                System.out.println(phantomReference.get());
            }
        }).start();

        new Thread(() -> {
            while(true){
                Reference<? extends Test1> poll = QUEUE.poll();
                if(poll != null){
                    System.out.println("虚引用对象被回收");
                }
            }
        }).start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

结果:
在这里插入图片描述
虚引用从头到尾无论是否gc都无法get到,当虚引用对象被清理时,会被放到队列中。一般虚引用用来垃圾回收时给系统一个通知。这里的应用场景是用于管理堆外内存。

总结

  • 强引用:发生 gc 的时候不会被回收。
  • 软引用:有用但不是必须的对象,在发生内存溢出之前会被回收。
  • 弱引用:有用但不是必须的对象,在下一次GC时会被回收。
  • 虚引用(幽灵引用/幻影引用):无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值