我们如何使HashMap类型的参数不可编辑?

时间:2013-03-21 14:45:20

标签: java

抱歉,我的头衔可能会产生误导。

这实际上来自我最近的一次JAVA采访,面试官问我这个问题:如果我们有一个HashMap类型的参数,我们怎样才能确保在接受方法中,用户无法做到修改这个HashMap(即get()方法)

我在面试中使用决赛,面试官根本没有欣赏,我在网上搜索这个话题已经有一段时间了但仍然没有任何线索。

专家能帮忙吗?感谢

7 个答案:

答案 0 :(得分: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. 在调用方法之前创建defensive copy
  2. 使用Collections
  3. 将对象包装在不可修改的包装中
  4. 使用显式不可变类型,例如Guava
  5. 提供的类型

答案 1 :(得分:1)

使用final并不妨碍在引用上调用方法。它只会使引用本身不可更改。所以你的回答是错误的。

我的建议是使用通用(仅用于此类访谈,而不是程序!):

    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(),所以这是游泳池安全概念。

此外,您可以使用一些包装器,这会在所有“写入”方法调用上抛出异常。

答案 2 :(得分:0)

如何从像here?

这样的Hashmap创建不可修改的Collection

然后你会这样做: yourMethod(Collections.unmodifiableMap(yourHashmap)); 仅使用final意味着您无法覆盖该引用与此块中的其他引用,它不会阻止该对象上的任何方法调用

答案 3 :(得分:0)

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

Collections#unmodifiableCollection

  

它返回指定地图的不可修改的视图。这种方法   允许模块为用户提供对内部的“只读”访问   地图。对返回的地图上的查询操作“通读”到   指定地图,并尝试修改返回的地图,是否直接   或通过其集合视图,产生一个   UnsupportedOperationException异常。

Reference

答案 4 :(得分:0)

使用Collections.unmodifiableMap

包裹您传递的地图

答案 5 :(得分:0)

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

答案 6 :(得分:0)

有两种方式

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

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