我个人完全同意你的看法。问题的核心在于 Java 的泛型不是协变的,这反过来又是因为 Java 的集合是可变的。
Java 的类型系统不可能编码一个看起来有mutators实际上是 immutable的类型。想象一下,如果我们要开始设计一些解决方案:
interface Immutable //marker for immutability
interface ImmutableMap<K, V> extends Map<K, V>, Immutable
但是 thenImmutableMap
是 的子类Map
,因此Map
可以从ImmutableMap
任何返回这种不可变 Map 的方法中赋值:
public ImmutableMap<K, V> foo();
可以分配给 Map,因此可以在编译时进行变异:
Map<K, V> m = foo();
m.put(k, v); //oh dear
因此,您可以看到添加这种类型实际上并没有阻止我们做任何坏事。我认为出于这个原因,做出了一个判断,它没有提供足够的东西。
像scala这样的语言具有声明站点差异注释。也就是说,您可以将类型指定为协变(因此是不可变的),因为 Scala 的 Map 是(实际上它的V
参数是协变的)。因此,您的 API 可以声明其返回类型是可变的还是不可变的。
另外,Scala 允许您声明交集类型,因此您甚至不需要将ImmutableXYZ
接口创建为单独的实体,您可以指定一个方法来返回:
def foo : XYZ with Immutable
但是 scala 有一个适当的类型系统,而 Java 没有