我如何要求参数成为可变映射?

How do I ask for a parameter to be a mutable Map?

我有一个接受 Map 个参数的函数,但在使用它们之前添加它们:

public String doRequest(String endpoint, Map<String, String> parameters) {
    parameters.put("limit", "50");
    ...
}

使用Guava的ImmutableMap.of()制作这张地图很方便:

doRequest("/comments", ImmutableMap.of("filter", "true"));

但是,这会在 运行 时抛出一个 java.lang.UnsupportedOperationException

两个问题:

1) 我能否以某种方式声明 doRequest,例如 HashMapTreeMap 没问题,但使用 ImmutableMap 会出现编译时错误?

2) 从 doRequest 内部,我如何检测到它是一个 ImmutableMap,所以我可以 运行 params = Maps.newHashMap(params)?

好吧,事实上 ImmutableMapMap 是错误的子类型并且违反了 LSP - 这是你为此付出的代价。子类型无法履行其父类型的合同...这是 ImmutableMap 继承自 map 是错误的 OOP(因为 Map 指定了 put)并且 Java 未提供足够强大的结构来执行这些保证。

至于解决方案 - document 您要改变传入的 Map,或者作为替代方案不要改变 Map 已传入 - 而不是 return 一个新的 ImmutableMap 你自己。

1) Can I declare doRequest in a way that for example HashMap and TreeMap would be fine but using ImmutableMap would be a compile time error?

没有。由于 ImmutableMap 实现了 Map,它不可能是编译时错误。问题实际上是 Map.put,它允许抛出。最好有一个没有 putMap 和一个 MutableMap 接口...但是在 Java 中没有任何人可以对此做任何事情,因为周围的所有软件都依赖于就可以了。

2) From inside doRequest, how would I detect that it's an ImmutableMap, so I could run params = Maps.newHashMap(params)?

你最好总是这样做,因为还有 Collections.unmodifiableMap 实际上每个人都可以实施 Map 拒绝 put

如果您关心性能,那么您需要 instanceof 检查。