如何声明该方法返回Collections.unmodifiableMap

时间:2013-09-25 15:25:34

标签: java hashmap unmodifiable

我正在从方法返回一个不可修改的地图。如何确保尝试修改返回的映射的任何代码都会出现编译时错误,而不是运行时错误?

我的课程:

public class Foo
{
    private final Map<String, Bar> aMap;

    public Foo()
    {
    ...
    }

    public Map<String, Bar> getMap(){
        return Collections.unmodifiableMap(aMap);
    }
}

我希望这会产生编译时错误:

Foo foo = new Foo();
Map<String, Bar> m = foo.getMap();
m.put('key',null); // user should be notified that the map is unmodifiable here, not at run time

我可以更改退货类型吗? 我可以添加适当的注释吗?

6 个答案:

答案 0 :(得分:4)

你可以创建一个像

这样的类
class ReadOnlyMap<K, V> {

    private final Map<K, V> map;

    public ReadOnlyMap(Map<K, V> map) {
       this.map = map;
    }

    public V get(Object key) {
        return map.get(key);
    }

    // also implement size() method
    // and everything else you want to expose
}

并将其用作方法的返回类型。那你的方法就是

public ReadOnlyMap<String, Bar> getMap() {
    return new ReadOnlyMap(aMap);
}

请注意,如果它们不是不可变类的实例,这不会妨碍调用者改变值对象。

答案 1 :(得分:2)

默认地图可以修改,期限。

如果您希望它不可修改,您必须编写自己的类,其中Map为变量,再次实现您需要的所有方法并将其传递给地图。

由于您不需要.put()方法,因此跳过该方法。

答案 2 :(得分:1)

您可以创建一个UnmodifiableMap对象,该对象具有Map接口的所有读取方法但缺少写入方法。该对象将包装您想要的地图。它看起来像是:

public class UnmodifiableMap<K, V> {

    private final Map<K, V> map;

    public UnmodifiableMap(final Map<K, V> map) {
        this.map = map;
    }

    public boolean containsKey(final K key) {
        return map.containsKey(key);
    }

    public V get(final K key) {
        return map.get(key);
    }

    // And so on.

}

请注意values()和entrySet()方法返回可修改的集合,因此您还需要包装它们返回的值。

答案 3 :(得分:0)

你不能这样做。

不可修改的集合是实现选项,而不是类型

你能做的最好的事情就是用javadoc来记录它,比如:

/**
 * Gets the map
 * @returns An unmodifiable Map
 */
public Map<String, Bar> getMap(){
    return Collections.unmodifiableMap(aMap);
}

答案 4 :(得分:0)

您不能使用标准类。使用标准类,您知道它是不可修改的唯一方法是尝试修改它并接收UnsupportedOperationException

您可以通过创建自己的UnmodifiableMap实现来实现编译时检查,该实现在内部使用正常Map(可能是不可修改的)。它将具有通常的“读取”操作,并且它们将被委托给基础Map。它不会有通常的“写”操作。我猜你也想要一个方法来返回底层的Map(或它的副本),以增强与其他代码的互操作性。

答案 5 :(得分:0)

这似乎接近你所要求的。它不会给出错误,但会发出警告!

public class Solid {
  // My map has no put.
  public interface Map<K, V> extends java.util.Map<K, V> {
    /**
     * Put to the Map.
     *
     * @deprecated SolidMap is unmodifiable. put() will fail!
     */
    @Deprecated
    @Override
    V put(K key, V value);

  }

  // Could also do this for lists etc.

  // Helper wrappers from each kind of map.
  public class HashMap<K, V> extends java.util.HashMap<K, V> implements Solid.Map<K, V> {
  }

  public class TreeMap<K, V> extends java.util.TreeMap<K, V> implements Solid.Map<K, V> {
  }
  //...

  // Test only.
  public void test() {
    Solid.Map<String, String> sm = new Solid.HashMap<>();
    // Warning that put is deprecated!
    String put = sm.put("Key", "Value");
  }

  public static void main(String args[]) {
    try {
      new Solid().test();
    } catch (Throwable t) {
      t.printStackTrace(System.err);
    }
  }

}