面试题答案
一键面试WeakHashMap的弱引用特性
WeakHashMap使用弱引用(Weak Reference)来关联键对象。这意味着,当键对象在系统的其他地方不再被强引用(即除了WeakHashMap内部对键的弱引用外,没有其他地方持有对该键的强引用)时,键对象可能会被垃圾回收器回收,即便WeakHashMap仍然存在。
当弱引用的键对象失去强引用后WeakHashMap的行为
当弱引用的键对象失去强引用并被垃圾回收时,WeakHashMap会在后续的某个时间点(例如,下一次调用 get
、put
、remove
等方法时)检测到该键已被回收,并自动将对应的键值对从WeakHashMap中移除。
举例说明
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
public class WeakHashMapExample {
public static void main(String[] args) {
// 创建一个WeakHashMap
WeakHashMap<Key, String> weakHashMap = new WeakHashMap<>();
// 创建一个强引用的键对象
Key key = new Key();
// 将键值对放入WeakHashMap
weakHashMap.put(key, "Value associated with key");
// 检查WeakHashMap中的键值对
System.out.println("WeakHashMap before key loses strong reference: " + weakHashMap);
// 使键对象失去强引用
key = null;
// 触发垃圾回收(注意,垃圾回收的时间不确定)
System.gc();
try {
// 等待一段时间,让垃圾回收有机会执行
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 再次检查WeakHashMap中的键值对
System.out.println("WeakHashMap after key loses strong reference: " + weakHashMap);
}
}
class Key {
@Override
protected void finalize() throws Throwable {
System.out.println("Key object is being garbage collected.");
}
}
在上述代码中:
- 首先创建了一个
WeakHashMap
并添加了一个键值对,键是Key
类型的对象。 - 然后将持有键对象的强引用置为
null
,使键对象失去强引用。 - 通过
System.gc()
尝试触发垃圾回收,并等待一段时间让垃圾回收有机会执行。 - 最后打印
WeakHashMap
,可以看到当键对象被垃圾回收后,对应的键值对也从WeakHashMap
中移除了。同时,Key
类的finalize
方法会在键对象被垃圾回收时打印一条信息,以证明键对象确实被回收了。
与之对比,如果使用普通的HashMap
,即使键对象失去强引用被垃圾回收,对应的键值对依然会保留在HashMap
中,因为HashMap
对键持有强引用。例如:
import java.util.HashMap;
import java.util.Map;
public class HashMapExample {
public static void main(String[] args) {
// 创建一个HashMap
HashMap<Key, String> hashMap = new HashMap<>();
// 创建一个强引用的键对象
Key key = new Key();
// 将键值对放入HashMap
hashMap.put(key, "Value associated with key");
// 检查HashMap中的键值对
System.out.println("HashMap before key loses strong reference: " + hashMap);
// 使键对象失去强引用
key = null;
// 触发垃圾回收(注意,垃圾回收的时间不确定)
System.gc();
try {
// 等待一段时间,让垃圾回收有机会执行
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 再次检查HashMap中的键值对
System.out.println("HashMap after key loses strong reference: " + hashMap);
}
}
class Key {
@Override
protected void finalize() throws Throwable {
System.out.println("Key object is being garbage collected.");
}
}
在这个HashMap
的例子中,即使键对象失去强引用并被垃圾回收,键值对仍然会保留在HashMap
中。