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

ygya80vv  于 2023-02-07  发布在  Java
关注(0)|答案(7)|浏览(152)

我正在从一个方法返回一个不可修改的Map。我如何确保任何试图修改返回的Map的代码将得到一个编译时错误,而不是运行时错误?
我的班级:

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

我可以改变返回类型吗?我可以添加适当的注解吗?

ttp71kqs

ttp71kqs1#

您可以创建一个类

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);
}

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

kmpatx3s

kmpatx3s2#

默认Map是可修改的,句号。
如果你希望它是不可修改的,你必须编写自己的类,把Map作为变量,再次实现你需要的所有方法,并把它传递给map。
因为您不需要.put()方法,所以跳过这个方法。

0lvr5msh

0lvr5msh3#

您可以创建一个UnmodifiableMap对象,它具有Map接口的所有读取方法,但缺少写入方法。此对象将 Package 您想要的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()方法返回的是 modifiable 集合,因此还需要 Package 它们的返回值。

yvfmudvl

yvfmudvl4#

你不能这么做。
不可修改的集合是一个 * 实现 * 选择,而不是一个 * 类型 *。
你能做的最好的事情就是用javadoc来记录它,类似于:

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

xxb16uws5#

你不能用标准类来做,用标准类,你知道它是不可修改的唯一方法是尝试修改它并接收一个UnsupportedOperationException
您可以通过创建自己的UnmodifiableMap实现(在内部使用常规Map)来实现编译时检查(可能是不可修改的)。它将具有通常的“读”操作,并且这些操作将委托给底层的Map。它将不具有通常的“写”操作。我猜您还希望有一个方法返回底层的Map(或其副本),以增强与其他代码的互操作性。

lmyy7pcs

lmyy7pcs6#

这似乎接近了你所要求的。它没有给予错误,但它确实给出了警告!

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);
    }
  }

}
zour9fqk

zour9fqk7#

目前我正在Jenkins中调试一个问题,然后遇到了Jenkins中的默认变量“prams”,使用echo params.getClass().getSimpleName()时,输出为UnmodifiableMap
然后找出***groovy***中的一个方法,该方法将返回一个UnmodifiableMap类:Map map = [:]def updatedMap = Collections.unmodifiableMap(map),则“更新Map”的类型是“不可修改Map”。

相关问题