JAVA的引用类型

强引用:=

软引用:SoftReference

弱引用:WeakReference

虚引用:PhantomReference

对象的可及性:

强可及对象:永远都不会被GC回收,除非OOM

软可及对象:当系统内存不足的时候,被GC回收

弱可及对象:当系统GC发现这个对象,就被回收

虚可及对象:虚引用用来检测对象是否被回收

引用队列(ReferenceQueue):

弱引用,软引用,虚引用中都存在两种构造器,第二种可以传一个引用队列,如果我们使用第二种构造参数创建引用对象时,这个引用对象就会被监听,一旦有对象被回收,所指向它的引用对象就会被添加到引用队列中,开发者可以把这个引用从队列中弹出,来判断对象是否被回收。

代码展示:

这里以String对象为例:

创建一个String对象,分别用强引用,弱引用,软引用指向这个对象

String string2=new String("abc");

//创建一个软引用,让它指向string2对象
SoftReference<String> sfr=new SoftReference<String>(string2);

//创建一个弱引用,让它指向string2对象
WeakReference<String> wrf=new WeakReference<String>(string2);

注意这里不能写成:String str="abc",因为"abc"是放在常量区中的,而gc是从堆内存中找垃圾对象。所以“abc”不会被回收

首先,我们删除强引用,主动gc,并打印软引用和弱引用的值:

string2=null;	//去掉强引用
System.gc();
System.out.println("软引用所引用对象的值:"+sfr.get());
System.out.println("弱引用所引用对象的值:"+wrf.get());

打印结果:

软引用所引用对象的值:abc
弱引用所引用对象的值:abc

我们发现删除强引用后,开启gc回收,gc并不会回收被软引用指向的对象。

然后,我们把软引用清空,再次主动gc,并打印弱引用的值

sfr.clear();
System.gc();
System.out.println(wrf.get());//对于弱可及对象,当系统GC发现这个对象,就被回收

打印结果:

null

我们发现当对象只剩下弱引用时,只要gc开始回收,这个对象就会被当成垃圾对象回收。

最后,我在这里写一下引用队列监听对象回收的测试:

private static void ReferenceQueueTest() {
	final ReferenceQueue<String> QUEUE=new ReferenceQueue<>();
	String str=new String("abc");
	//虚引用用来检测对象是否被回收
	PhantomReference<String> prf=new PhantomReference<String>(str,QUEUE);
	WeakReference<String> wrf=new WeakReference<String>(str,QUEUE);
	new Thread(new Runnable() {
		@Override
		public void run() {
			while(true){
				Reference<? extends String> poll = QUEUE.poll();
				if(poll!=null){	//对象被回收
					System.out.println("--- 引用对象被回收 ---- " + poll);
                                        System.out.println("--- 回收对象 ---- " + poll.get());
				}
			}
		}
	}).start();

	try {
		Thread.sleep(2000);	//这里模拟对象的生存时间,两秒后强引用被删除,对象被回收
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
	str=null;	 //删除强引用
	System.gc();	//主动gc
}

打印结果:

--- 引用对象被回收 ---- java.lang.ref.WeakReference@513065ba
--- 回收对象 ---- null
--- 引用对象被回收 ---- java.lang.ref.PhantomReference@5ff781ec
--- 回收对象 ---- null

我这里用了一个子线程来等待引用对象进入引用队列,我们将String对象的强引用删除,然后主动gc,这样子String对象就会被回收。回收后,上面测试中的弱引用对象和虚引用对象就都被放入了引用队列中。我们将引用对象弹出队列,就可以检查String对象是否被回收了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值