当clear()方法调用抛出UnsupportedOperationException时,如何清除映射的内容?

时间:2013-02-08 12:01:54

标签: java exception collections

当我在地图实例上调用UnsupportedOperationException方法时,如果我继续获得clear(),我该如何清空地图内容?

2 个答案:

答案 0 :(得分:2)

你不应该。合作对象及其方法的合同存在问题。您期望可修改的地图,但获得不可修改的视图。您应该重新定义合同和/或相应地采用任何实现。如果你无法控制那个通过你那张地图的人,那么可能有一个理由让你传递一个不可修改的观点。

答案 1 :(得分:0)

如果MapUnmodifiableMap(例如,来自Collections.unmodifiableMap()),那么您可以(并且应该)修改它,除了创建一个新的引用并清除它。

Map unmodifiable = Collections.unmodifiableMap(m);
Map newMap = new HashMap(unmodifiable);
newMap.clear();
unmodifiable = newMap;

尽管如此,实际上可以修改UnmodifiableMap。事实证明,Collections.UnmodifiableMap只不过是一个实现Map接口的类,并包含实际的Map。它为包装的Map委托其只读方法,并在其改变地图的方法实现中抛出UnsupportedOperationException。可以通过反射获取包装的Map,从而对其进行修改。

免责声明:请注意,必须谨慎使用。如果不可修改的地图由库或类似物提供,则可能对其性质做出假设,违反其合同可能导致意外/不良结果。此外,这可能依赖于可能在没有通知的情况下进行更改或内部版本不同的内部结构。

// Creates a standard map
Map<String, String> myMap = new HashMap<String, String>();
myMap.put("1", "a");
myMap.put("2", "b");
// Creates an unmodifiableMap. Actually a wrapper for myMap.
Map unmodifiableMap = Collections.unmodifiableMap(myMap);
System.out.println("Size of unmodifiable map is: " + unmodifiableMap.size());
try{
    // Get classes declared in java.util.Collections
    Class[] classes = Collections.class.getDeclaredClasses();
    for(Class cl : classes) {
        // Look for the UnmodifiableMap class
        if("java.util.Collections$UnmodifiableMap".equals(cl.getName())) {
            // The wrapped Map is in an attribute called "m"
            Field field = cl.getDeclaredField("m");
            field.setAccessible(true);
            // Get the wrapped map
            Object obj = field.get(unmodifiableMap);
            Map map = (Map) obj;
            // modify it
            map.clear();
        }
    }
}
catch (Exception e){ System.out.println(); }
System.out.println("Size of unmodifiable map is: " + unmodifiableMap.size());

(归功于this blog post