java - 为什么 Java 有 4 种不同类型的引用?
问题描述
直到今天,我还不知道 Java 有四种主要的引用类型。
- 强引用:
Java
使用的默认引用类型。 - 弱引用:如果一个对象有一个弱引用,那么
GC
即使有足够的内存,也会在下次运行时回收这个对象的内存。 - 软引用:如果一个对象有一个软引用,那么
GC
只有当它非常需要一些内存时才回收这个对象的内存。 - 幻影引用:如果一个对象有一个幻影引用,那么它就有资格进行垃圾回收。但是,在 GC 之前,JVM 将应该被垃圾收集的对象放入一个名为
reference queue
.
我了解了基本概念并编写了一个小程序来了解每种引用类型的工作原理。
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
class User
{
public User info()
{
System.out.println("Info method invoked from User class");
return null;
}
}
public class ReferencesExample
{
public static void main(String[] args)
{
//Strong Reference
User userRefObj = new User();
System.out.println("1 :" + userRefObj.info());
// Weak Reference
WeakReference<User> weakref = new WeakReference<User>(userRefObj.info());
System.out.println("2 : " + weakref);
// Soft Reference
SoftReference<User> softref = new SoftReference<User>(userRefObj.info());
System.out.println("3 : " + softref);
// Phantom Reference
ReferenceQueue<User> refQueueObj = new ReferenceQueue<User>();
PhantomReference<User> phantomRef = new PhantomReference<User>(userRefObj.info(),refQueueObj);
System.out.println("4 : " + phantomRef);
}
}
输出 :
1 :null
Info method invoked from User class
Info method invoked from User class
2 : java.lang.ref.WeakReference@15db9742
Info method invoked from User class
3 : java.lang.ref.SoftReference@6d06d69c
Info method invoked from User class
4 : java.lang.ref.PhantomReference@7852e922
疑问:我们如何决定在现实世界场景中使用哪种引用类型以及在何处使用?
解决方案
这是一个复杂的答案,尤其是“现实世界”部分。这些特殊的参考资料是一个(非常)锋利的工具,它应该很少被触及并且非常好理解。您的第一个误解是只Phantom References
使用queue
(称为ReferenceQueue
)。事实上,他们都使用queue
. PhantomReference
在所有这些中有点“怪异”,主要是因为它周围的规范已从 更改java-8
为java-9
. 您可以阅读此答案以获取一些详细信息(目前尚不清楚使实例保持活动状态的原因java-8
)。
然后您得到的常见误解是“下一次运行”,有关更多详细信息,您可以查看此处。这里的“第二个”或“下一个”的概念有点棘手。但关键是这是不确定的。
提供“真实世界”的例子也有点棘手。发生这种情况是因为您很少直接使用这些引用,它们通常预先打包在实用程序中。例如,您可以查看 WeakHashMap 的工作原理(直接在后台使用WeakReference
and ReferenceQueue
),或事件this answer。guava
由于它CacheBuilder
曾经提供一些处理SoftReferences
(但不再)的 功能,但咖啡因仍然可以。
PhantomReferences
在内部用于Cleaner API
(since java-9
)。这是一个显示其一般用法的示例。没有PhantomReferences
,这实际上是不可能的(至少不是那么“容易”)。
在这个程度上,我们WeakHashMap
在生产中使用(我们也使用Cleaner API
,但少得多)。如果你真的想了解它们,你需要了解 a 是如何garbage collector
工作的(比如,真的有效),然后阅读他们的官方文档并尝试(并询问)多种事情。