MST

星途 面试题库

面试题:Java中WeakHashMap的弱引用特性基础

请简述Java中WeakHashMap的弱引用特性,当弱引用的键对象失去强引用后,WeakHashMap会发生什么?请举例说明。
30.5万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

WeakHashMap的弱引用特性

WeakHashMap使用弱引用(Weak Reference)来关联键对象。这意味着,当键对象在系统的其他地方不再被强引用(即除了WeakHashMap内部对键的弱引用外,没有其他地方持有对该键的强引用)时,键对象可能会被垃圾回收器回收,即便WeakHashMap仍然存在。

当弱引用的键对象失去强引用后WeakHashMap的行为

当弱引用的键对象失去强引用并被垃圾回收时,WeakHashMap会在后续的某个时间点(例如,下一次调用 getputremove 等方法时)检测到该键已被回收,并自动将对应的键值对从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.");
    }
}

在上述代码中:

  1. 首先创建了一个WeakHashMap并添加了一个键值对,键是Key类型的对象。
  2. 然后将持有键对象的强引用置为null,使键对象失去强引用。
  3. 通过System.gc()尝试触发垃圾回收,并等待一段时间让垃圾回收有机会执行。
  4. 最后打印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中。