0

抱歉,我的标题可能具有误导性。

这其实是我最近的一次JAVA面试,面试官问了我一个问题:如果我们有一个HashMap类型的参数,如何保证在accepting方法中,用户无法修改这个HashMap (即 get() 方法)

我在面试的时候说用final,面试官根本不领情,我在网上搜索了一段时间还是没有头绪。

专家能帮忙吗?谢谢

4

7 回答 7

1

听起来您可能来自 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();
}

有几种方法可以防止这种情况:

  1. 在调用方法之前制作一个防御性副本
  2. 使用Collections将对象包装在不可修改的包装器中
  3. 使用明确的不可变类型,例如Guava提供的类型
于 2013-03-21T14:49:53.833 回答
1

使用 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(),所以它是一个非常池安全的概念。

您也可以使用一些包装器,这会在所有“写入”方法调用上引发异常。

于 2013-03-21T14:58:25.710 回答
0

从这里的 Hashmap 创建一个不可修改的集合怎么样

然后你会这样做: yourMethod(Collections.unmodifiableMap(yourHashmap)); 使用 final 只意味着你不能用这个块中的另一个引用覆盖那个引用,它不会阻止对该对象的任何方法调用。

于 2013-03-21T14:47:09.683 回答
0

我认为这是不可变或不可修改的地图。

Collections#unmodifiableCollection

它返回指定地图的不可修改视图。此方法允许模块为用户提供对内部地图的“只读”访问权限。对返回的映射“通读”到指定映射的查询操作,并尝试修改返回的映射,无论是直接还是通过其集合视图,都会导致 UnsupportedOperationException。

参考

于 2013-03-21T14:48:39.503 回答
0

使用Collections.unmodifiableMap包装您传递的地图

于 2013-03-21T14:49:29.330 回答
0

Collections.unmodifiableMap(myMap)将返回只读映射。您应该处理由此返回的 Map 对象。

于 2013-03-21T14:50:44.323 回答
0

有2种方式

1) this.map = Collections.unmodifiableMap(map);

2)防御性复制:this.map = new HashMap(map);

于 2013-03-21T14:59:04.087 回答