首页 > 解决方案 > HashMap 中的强引用

问题描述

我试图理解强引用和弱引用,在 WeakHashMap 的帮助下我们可以轻松实现,但是我们如何在 HashMap 中实现呢?当我使用下面的代码时,String s3 不是垃圾收集,为什么会这样?

HashMap<String,String> wh=new HashMap<String,String>();
String s1=new String("Google");
String s2=new String("Microsoft");
String s3=new String("Apple");
wh.put(s1, "Search Engine");
wh.put(s2, "OS");
wh.put(s3, "Mac");
System.out.println(wh);
//s3=null;
WeakReference<String> wf=new WeakReference<>(s3);
s3=null;
System.gc();
System.out.println(wh); 



// Output-{Google=Search Engine, Apple=Mac, Microsoft=OS}

当我对 WeakHashMap 做同样的事情时,它工作得很好。

WeakHashMap<String, String> wh = new WeakHashMap<String, String>();
String s1 = new String("Google");
String s2 = new String("Microsoft");
String s3 = new String("Apple");
wh.put(s1, "Search Engine");
wh.put(s2, "OS");
wh.put(s3, "Mac");
System.out.println(wh);
s3 = null;
System.gc();
System.out.println(wh);

标签: java

解决方案


这是因为仍然会有一个HashMap键引用该s3对象用来引用的字符串:

HashMap<String,String> wh = new HashMap<String,String>();

// s1 and s2 remain the same (omitted for brevity)
String s3 = new String("Apple");

// Here you are adding a Map Entry whose key is referencing `s3` (or more explicitly, the same String `s3` is referencing)
wh.put(s3, "Mac");

// Here you are declaring a `WeakReference` to the same String, but that String is still referenced in a `Map.Entry` key (from above HashMap)
WeakReference<String> wf = new WeakReference<>(s3);

// Nullifying s3 adds nothing as well, as you are only setting the local variable s3 to null (still the same String that s3 used to reference referenced by the Map.Entry key)
s3 = null;

// Calling the Garbage Collector won't collect the String object that s3 used to reference (since there still a hard reference in the Map.Entry referencing it) 
System.gc();

// So you will still get the String content (that 's3' used to reference) when you print `wh` since it still has an entry referencing the same String that have not been garbage collected
System.out.println(wh);

请注意,除了您对 s3 的弱引用的混淆假设之外,不能保证 GC 将System.gc() 在 JDK API 中记录的a 上运行:

无法保证此工作将回收任何特定数量的未使用对象,回收任何特定数量的空间,或在任何特定时间(如果有的话)在方法返回之前或永远完成。


推荐阅读