java中的引用,你注意到没?

本文深入探讨Java中的四种引用类型:强引用、软引用、弱引用和幻象引用。解析每种引用的特点及其应用场景,尤其强调如何利用不同类型的引用解决内存溢出等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


======================================================
注:本文源代码点此下载
======================================================

java中没有指针,到处都是引用(除了基本类型)。所以,当然,你肯定知道java的引用,并用了很久,但是是不是对此了解地比较全面?而这些引用有什么作用,且有什么不同呢?

java中有个java.lang.ref包,这里面都是描述引用对象的,包括了reference,softreference,weakreference和phantomreference。其中,reference是基类其他三个类的基类。下面就这几种引用对象做个说明。

强引用(strong references)

我们每天都在用强引用(如果你每天都在用java的话),一段如下的代码:

hashmap mapref = new hashmap();

就是通过new

hashmap();创建了一个对象(这东西在heap上),并把一个强引用存到了 mapref引用中。而强引用之为“强”的地方就在于其对垃圾回收器所产生的影响。如果一个对象可以经由一条强引用链可达(也就说这个对象是strongly

reachable),那么就说明这个类不适合被垃圾回收。我们也绝对不希望正在使用的对象一下子了无踪迹了。

但是强引用会对我们的应用产生很“强”的影响。比如:经常会碰到一个问题,缓存。通过set(以set为例吧)模拟的缓存,在应用运行的过程中,会不断有

大量对象添加到set中。这些对象并不会被gc回收,并且随着对象的增多,我们的内存也会不断变大,终于有一天outofmemory啦。其实,set可

能使用频率还不大,hashmap的key-value模式让我们爱不释手,引诱着你去不断地put,put,扑通。。outofmemory啦。

对于java这门有魅力,有活力,有朝气,有老气,有垃圾自动回收机制的语言而言,我们不应被上述问题所困扰。

弱引用(weak reference)

弱引用,就是不是那种用强制的方式要求对象存在于内存的引用。可以借助垃圾回收器来判断某个对象的可达性,并帮你回收弱引用所引用的对象。如何创建一个弱引用呢:

stringbuffer sbuff = new stringbuffer("what is a weakreference?");

weakreference wref = new weakreference(sbuff);

sbbuff=null;//这里的操作,看情况定。在这里主要为了说明,原来强引用的一个对象,被转成一个弱引用来指向。

然后通过wref.get()来获取sbuff对象。因为弱引用并没强悍到可以阻止垃圾回收器回收wref引用的对象(这里要区分引用对象和被引用的对象,在创建一个 weakreference时,就有一个引用对象诞生了,它指向了一个被引用的对象),所以可能从某一刻开始,wref.get()就开始给我们null了。

对于上面提到的使用hashmap时,对象过多(并且不删除,而被垃圾回收)会造成的outofmemory问题,可以通过weakhashmap来实现,这样垃圾回收器就会帮我们处理那些时间长了不用,还占地方的类了,而不至于出现outofmemory问题。

引用队列(referencequeue,何方神圣?)

当weakreference开始返回null时,说明它原来指向的对象已经变成了垃圾。另外也说明这个weakreference对我们已经没多少用处了。我们需要做点什么来处理这些没用的东西?

逢此危难之际,referencequeue闪亮登场。据官方资料,其定义为:

reference queues, to which registered reference objects are appended by the

garbage collector after the appropriate reachability changes are detected.

(当检测到相应的可达性发生改变后,垃圾回收器就会将注册有此队列的引用对象添加到这个引用队列中。)

如何注册一个队列?在weakreference的构造函数中,有一个weakreference(t referent,

referencequeuet> q)。所以,当一个weakreference变成一个死引用时,它就会被添加到这个referencequeue中,只要定期的来处理一下这个referencequeue就可以了。

不同的引用

引用实际上是有好几种的,就如我们在java.lang.ref包中看到的那样,再加上强引用,有4种引用类型:强(strong)、软(soft)、弱(weak)、幻象(phantom),引用依次从强到弱。接下来,就看看其他的引用。

软引用(soft reference)

软引用,跟弱引用功能挺像的。但是软引用指向的对象一般会比弱引用的存活时间长一些,直到内存空间不够时,才会被垃圾回收。一个weakly reachable对象,是仅仅被weakreference引用的,并且会被垃圾回收器在下一个垃圾回收周期中丢弃;而一个softly reachable对象,则会活地时间长一些。

软引用给我们带来了很大的实惠,尤其是缓存的实现。比如,我们有一个缓存池,对于内存比较紧张的情况来说,一旦要达到memory上限时,垃圾回收器就将soft reference引用的对象释放掉,以避免outofmemory惨剧的发生。

幻象引用(phantom reference)

幻象引用,是不同于soft和weak的引用。幻象引用对指向对象的引用强度如此之脆弱,以至于调用方法get()时,总是返回null。它的主要作用就是跟踪所指向的对象已经dead了,那么其跟weakreference的区别是什么呢?

它们的区别就在于:是在什么时候,这个引用对象被添加到引用队列中的。weakreference是在当其所引用的对象变成weakly reachable时被添加到引用队列中的,这发生在一个对象被finalization或被垃圾回收之前的。理论上讲,一个对象在被finalize()时,是可以被“复活”的,但此时weakreference已经没活力了。对幻象引用来说,只有当其所引用的对象被彻底垃圾回收(从内存中消除)时,才会添加到引用队列中。而幻象引用的get方法总是返回null,就是要避免我们来“复活”一个奄奄一息的对象。

那么幻象引用有何实际作用?

第一、我们可以在监控一个对象什么时候被彻底销毁了。那样,就可以做点什么其他事情(看你是不是有这方面的需求啦)。不过实际中,这种情况也不多的。

第二、因为理论上存在的,可以通过一个对象的finalize()方法“复活”一个对象,那么如果在一次垃圾回收处理时,调用了一个对象的finalize()(这个方法在何时调用不确定),却让它复活了。要再苦苦等待finalize()的执行,还不知道要到猴年马月的(天下大赦可以有,但不是天天有。谁知道啥时候天朝更替,人主易位)。突然就出现了outofmemory错误了。

而幻象引用绝对不会再让对象复活,只要被它逮着了,事情就简单了:挂定了!

总而言之,言而总之,归根结底:

引用是关系垃圾回收的。


======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值