ImmutableList不扩展List?

Win*_*ins 6 java collections gs-collections

当我深入研究gs-collection源代码时ImmutableList,它不会扩展java.util.List.但是,类javadoc提到All ImmutableList实现必须实现java.util.List.

为什么必须要求实现实现java.util.List而不是ImmutableList自己扩展java.util.List

Cra*_*lin 12

为什么不ImmutableList延长List

ImmutableCollection不扩展java.util.Collection(并且ImmutableList不扩展java.util.List),因为Collection有像add()和的变异方法remove().如果不可变集合具有这些方法,则它们总是必须抛出UnsupportedOperationException.对于不可改变的集合的用户,这将是奇怪地看到add(),并remove()在自动完成选择,如可调用的方法.

为什么Javadoc强制要求所有ImmutableList实现都实现的合同List

归结为平等.一个ImmutableList应该等于一个List,假设两个列表具有相同的顺序相同的内容.List.equals()强制执行Javadoc合同,其中规定:

当且仅当指定的对象也是列表时,返回true,两个列表具有相同的大小,并且两个列表中的所有对应元素对都相等.

"指定的对象也是一个列表是什么意思?" 我们可以看出AbstractList.equals()它意味着instanceof List.

public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof List))
        return false;
    ...
}
Run Code Online (Sandbox Code Playgroud)

因此,所有ImmutableList的实现也必须实现Listequals()以对称的方式工作.不可变集合工厂已经隐藏了实现细节,例如具有单个元素的不可变列表由a实现ImmutableSingletonList.它还最终隐藏了List界面.

ImmutableList类图

互操作

这种设计的一个好处是ImmutableList可以强制转换List为与现有API互操作的重要性.

// Library method - cannot refactor the parameter type
public void printAll(List<?> list)
{
    for (Object each : list)
    {
        System.out.println(each);
    }
}

ImmutableList<Integer> immutableList = Lists.immutable.with(1, 2, 3);
List<Integer> castList = immutableList.castToList();
printAll(castList);
// also works
printAll((List<?>) immutableList);

// throws UnsupportedOperationException
castList.add(4);
Run Code Online (Sandbox Code Playgroud)

注意:我是GS Collections的开发人员.

  • 感谢长时间的回答,这是有道理的,但我猜这是一种设计风格.就个人而言,我更喜欢使用add()和remove()来抛出UnsupportedOperationException,而不是调用castToList().开发人员应该知道,如果代码使用的是ImmutableList,添加和删除将不起作用,这是开发人员的问题,而不是设计问题.但我想这只是个人观点.再次感谢您的回答 (2认同)
  • 我想你可能对UnmodifiableMutableList及其工厂方法MutableList.asUnmodifiable()感兴趣.我把这个答案限制在ImmutableList,但随便问一个关于差异的新问题,我会回来写更多. (2认同)
  • 我理解UnmodifiableMutableList(名称非常明确),但我要问的是为什么不使ImmutableList扩展List,在添加和删除时抛出UnsupportedOperationException,但保留列表及其包含的对象的不变性. (2认同)
  • 你所描述的肯定会奏效.它归结为设计权衡.UnsupportedOperationExceptions令人困惑且难以处理,尽管可能没有比上面的类图更令人困惑.如果我们在ImmutableList上有变异方法,我们也可以将它们拉到父ListIterable.然后MutableList和ImmutableList将变为空标记接口,这是奇数.我们可以删除它们,但是ListIterable.add()可能会也可能不会抛出.当前设计的缺点是互操作.优点是能够清楚地表达意图,特别是对于田地. (2认同)