81

有人可以解释三个参考类之间的区别(或发布一个很好的解释的链接)吗?SoftReference> WeakReference> PhantomReference,但我什么时候会使用每一个?为什么有一个WeakHashMap但没有SoftHashMapPhantomHashMap

如果我使用以下代码...

WeakReference<String> ref = new WeakReference<String>("Hello!");
if (ref != null) {                 // ref can get collected at any time...
    System.gc();                   // Let's assume ref gets collected here.
    System.out.println(ref.get()); // Now what?!
}

...怎么了?我是否必须ref在每条语句之前检查是否为空(这是错误的,但我该怎么)?很抱歉这些快速的问题,但我无法理解这些Reference课程......谢谢!

4

4 回答 4

60

该包的 Java 库文档java.lang.ref描述了三种显式引用类型的递减强度。

SoftReference当您希望被引用的对象保持活动状态直到主机进程的内存不足时,您可以使用。在收集器需要释放内存之前,该对象将不符合收集条件。简单地说,绑定SoftReference意味着“固定对象,直到你不能再固定为止”。

相反,WeakReference当您不想影响被引用对象的生命周期时,使用 a;您只想对引用的对象进行单独的断言只要它仍然存在。对象的收集资格不受 bound WeakReferences 存在的影响。像从对象实例到相关属性的外部映射,只要相关对象还活着,就需要记录属性,这对于WeakReferences 和WeakHashMap.

最后一个——<code>PhantomReference——更难描述。就像 一样WeakReference,这样的界限PhantomReference对被引用对象的生命周期没有影响。但与其他引用类型不同,甚至不能取消引用 a PhantomReference。从某种意义上说,就调用者所知,它并不指向它所指向的东西。它仅允许将一些相关数据与引用的对象相关联——这些数据稍后可以PhantomReference在其相关对象中排队时进行检查和操作ReferenceQueue。通常,从该派生类型派生一个类型PhantomReference并在该派生类型中包含一些附加数据。不幸的是,使用这种派生类型需要进行一些向下转换。

在您的示例代码中,它不是ref可以为空的引用(或者,如果您愿意,“变量”)。相反,它是通过调用获得的值Reference#get()可能为空。如果发现为null,那就来不及了;引用的对象已经在被收集的路上:

final String val = ref.get();
if (null != val)
{
  // "val" is now pinned strongly.
}
else
{
  // "val" is already ready to be collected.
}
于 2010-07-25T15:27:36.070 回答
6

链接:https ://community.oracle.com/blogs/enicholas/2006/05/04/understanding-weak-references

PhantomHashMap不会很好地工作,因为get总是返回null幻影引用。

缓存很困难,所以SoftHashMap可能没有你想象的那么好。但是,我相信 Google 的收藏库包含一个通用的参考地图实现。

您应该始终检查get返回非null. (请注意,不检查Reference引用本身是否不是- null。)对于实习字符串,它总是会,但(一如既往)不要试图“聪明”地处理它。

于 2010-07-25T15:25:10.293 回答
3

正如Truong Xuan Tinh 的评论所述,还应该提到它:http: //blog.yohanliyanage.com/2010/10/ktjs-3-soft-weak-phantom-references/

JRockit JVM 实现弱/软/幻像引用的方式与 Sun JVM 不同。

于 2013-08-02T17:04:13.920 回答
0
String str = new String("hello, world");
WeakReference<String> ref = new WeakReference<String>(str);
str = null;

if (ref != null) {                 
    System.gc(); 
    System.out.println(ref.get());
}

在这种情况下,它将输出 null。这里的调用System.gc()很重要。

于 2016-03-04T18:29:43.123 回答