浅谈java中的几种引用

话不多说,这篇文章主要聊一下自己对java中几种引用的区别与用途的理解吧,虽然实际项目开发中用的并不多,但是对拓宽自己的知识面还是很有必要的。

1.强引用

强引用就是我们经常使用的引用,其写法如下

StringBuffer buffer = new StringBuffer();

上面创建了一个StringBuffer对象,并将这个对象的引用存到变量buffer中。强引用最重要的就是它能够让引用变得强,也就决定了它和垃圾回收器的交互。具体地说,如果一个对象通过一串强引用的链接可到达的话,它是不会被回收的。如果你不想让你正在使用的对象被回收,那就优先选择使用强引用吧。

但是强引用是如此的强,先看下面的代码

map.put(strongRef,strongRefSerialNumber);

当我们不需要使用强引用对象序列号时,我们需要把strongRef从map中去除,如果没有删除,可能会出现内存泄露,但是如果我们手动删除正在使用的strongRef的话,会导致数据的丢失,这是没有垃圾回收机制的语言管理内存时常遇到的问题。但是我们不用去担心这个问题,因为我们使用的时具有垃圾回收机制的Java语言。

另一个强引用可能带来的问题就是缓存,尤其是像图片这样的大文件的缓存。假设你有一个程序需要处理用户上传的图片,通常的做法就是做图片数据缓存,因为从磁盘加载图片的代价很大,并且同时我们也要避免在内存中同时存在两份一样的图片数据。

缓存设计的目的就是避免我们去再次加载哪些不需要的文件。你会很快发现在缓存中会一直包含一个到已经指向内存中图片数据的引用。使用强引用会强制图片数据留在内存,这就需要你来决定什么时候图片数据不需要并且手动从缓存中移除,进而可以让垃圾回收器回收。因此你再一次被强制做垃圾回收器该做的工作,并且人为决定该清理到哪一个对象。

2.弱引用

弱引用简单来说就是将对象留在内存的能力不是那么强的引用。使用WeakReference,垃圾回收器会帮你来决定引用的对象何时回收并且将对象从内存移除。创建弱引用如下

WeakReference<Widget> weakWidget = new WeakReference<Widget>(widget);

使用weakWidget.get()就可以得到真实的Widget对象,因为弱引用不能阻挡垃圾回收器对其回收(弱引用对象必然会在下一次GC中被回收),你会发现(当没有任何强引用到widget对象时)使用get时突然返回null。

解决上述强引用中的strongRef序列数记录的问题,最简单的办法就是使用Java内置的WeakHashMap类。WeakHashMap和HashMap几乎一样,唯一的区别就是它的键(不是值!!!)使用WeakReference引用。当WeakHashMap的键标记为垃圾的时候,这个键对应的条目就会自动被移除。这就避免了上面不需要的strongRef对象手动删除的问题。使用WeakHashMap可以很便捷地转为HashMap或者Map。

引用队列(Reference Queue)


一旦弱引用对象开始返回null,该弱引用指向的对象就被标记成了垃圾。而这个弱引用对象(非其指向的对象)就没有什么用了。通常这时候需要进行一些清理工作。比如WeakHashMap会在这时候移除没用的条目来避免保存无限制增长的没有意义的弱引用。

引用队列可以很容易地实现跟踪不需要的引用。当你在构造WeakReference时传入一个ReferenceQueue(引用队列)对象,当该引用指向的对象被标记为垃圾的时候,这个引用对象会自动地加入到引用队列里面。接下来,你就可以在固定的周期,处理传入的引用队列,比如做一些清理工作来处理这些没有用的引用对象。

3.软引用

软引用基本上和弱引用差不多,只是相比于弱引用,它阻止垃圾回收期回收其指向的对象的能力强一些。如果一个对象是弱引用可到达,那么这个对象会被垃圾回收器接下来的回收周期销毁。但是如果是软引用可以到达,那么这个对象会停留在内存更时间上长一些。当内存不足时垃圾回收器才会回收这些软引用可到达的对象。

由于软引用可到达的对象比弱引用可达到的对象滞留内存时间会长一些,我们可以利用这个特性来做缓存。这样的话,你就可以节省了很多事情,垃圾回收器会关心当前哪种可到达类型以及内存的消耗程度来进行处理。

4.虚引用

与软引用,弱引用不同,虚引用指向的对象十分脆弱,我们不可以通过get方法来得到其指向的对象。它的唯一作用就是当其指向的对象被回收之后,自己被加入到引用队列,用作记录该引用指向的对象已被销毁。

当弱引用的指向对象变得弱引用可到达,该弱引用就会加入到引用队列。这一操作发生在垃圾回收真正发生之前。虚引用只有在其指向的对象从内存中移除掉之后才会加入到引用队列中。

虚引用使用场景主要由两个。它允许你知道具体何时其引用的对象从内存中移除。这一点尤其表现在处理类似图片的大文件的情况。当你确定一个图片数据对象应该被回收,你可以利用虚引用来判断这个对象回收之后在继续加载下一张图片。这样可以尽可能地避免内存溢出错误。

以上就是我个人对java中的四种引用的个人理解,如果有不同意或错漏的地方,请联系我

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值