抱歉,我的标题可能具有误导性。
这其实是我最近的一次JAVA面试,面试官问了我一个问题:如果我们有一个HashMap类型的参数,如何保证在accepting方法中,用户无法修改这个HashMap (即 get() 方法)
我在面试的时候说用final,面试官根本不领情,我在网上搜索了一段时间还是没有头绪。
专家能帮忙吗?谢谢
抱歉,我的标题可能具有误导性。
这其实是我最近的一次JAVA面试,面试官问了我一个问题:如果我们有一个HashMap类型的参数,如何保证在accepting方法中,用户无法修改这个HashMap (即 get() 方法)
我在面试的时候说用final,面试官根本不领情,我在网上搜索了一段时间还是没有头绪。
专家能帮忙吗?谢谢
听起来您可能来自 C++ 背景,在这种情况下,设置参数const
确实会阻止方法修改对象。在 Java 中,final
仅阻止分配给该变量;您仍然可以调用修改对象本身的方法。
因此,例如:
void callingMethod() {
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(1, 2);
badMethod(map);
// NullPointerException
System.out.println(map.get(1).intValue());
}
void badMethod(final HashMap<Integer, Integer> map) {
map.clear();
}
有几种方法可以防止这种情况:
使用 offinal
不会阻止调用引用上的方法。它只会使引用本身不可更改。所以你的答案是错误的。
我的建议是使用泛型(仅用于此类采访,而不是在程序中!):
Map<String, String> map = new HashMap< String, String >();
map.put("a", "b"); // OK
Map< ? extends String, ? extends String > mapRO = new HashMap< String, String >();
mapRO.put("a", "b"); // Compile error
String value = mapRO.get("a"); // OK
如您所见,隐藏泛型类型会? extends ...
阻止put
调用“写入”方法(如 ),因为它们通常需要完全定义类型。但是你仍然可以调用clear()
,所以它是一个非常池安全的概念。
您也可以使用一些包装器,这会在所有“写入”方法调用上引发异常。
从这里的 Hashmap 创建一个不可修改的集合怎么样?
然后你会这样做:
yourMethod(Collections.unmodifiableMap(yourHashmap));
使用 final 只意味着你不能用这个块中的另一个引用覆盖那个引用,它不会阻止对该对象的任何方法调用。
我认为这是不可变或不可修改的地图。
Collections#unmodifiableCollection
它返回指定地图的不可修改视图。此方法允许模块为用户提供对内部地图的“只读”访问权限。对返回的映射“通读”到指定映射的查询操作,并尝试修改返回的映射,无论是直接还是通过其集合视图,都会导致 UnsupportedOperationException。
使用Collections.unmodifiableMap包装您传递的地图
Collections.unmodifiableMap(myMap)
将返回只读映射。您应该处理由此返回的 Map 对象。
有2种方式
1) this.map = Collections.unmodifiableMap(map);
2)防御性复制:this.map = new HashMap(map);