ImmutableList 不扩展 List?

ImmutableList does not extend List?

当我深入研究 ImmutableList 的 gs-collection 源代码时,它没有扩展 java.util.List。但是 class javadoc 提到所有 ImmutableList 实现必须实现 java.util.List.

为什么必须要求实施来实施 java.util.List 而不是 ImmutableList 本身来扩展 java.util.List

为什么 ImmutableList 不扩展 List

ImmutableCollection doesn't extend java.util.Collection (and ImmutableList 不扩展 java.util.List) 因为 Collection 有像 add()remove() 这样的变异方法。如果不可变集合有这些方法,它们总是必须抛出 UnsupportedOperationException。对于不可变集合的用户,将自动完成选项中的 add()remove() 视为可调用方法会很奇怪。

为什么 Javadoc 强加了所有 ImmutableList 实现也实现 List 的契约?

归结为平等。 ImmutableList 应该等于 List,假设两个列表的内容相同且顺序相同。 List.equals() imposes a Javadoc contract 其中指出:

Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal.

"the specified object is also a list?"是什么意思 我们在AbstractList.equals()中可以看出是instanceof List.

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

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

互操作

此设计的一个好处是 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);

注意:我是 GS Collections 的开发者。