在Java 9中,我们有方便工厂方法来创建和实例化不可变的List,Set和Map。
但是,目前还不清楚返回对象的具体类型。
例如:
List list = List.of("item1", "item2", "item3");
在这种情况下,实际返回了哪种类型的列表?它是ArrayList还是LinkedList或其他类型的List?
API文档刚提到这一行,没有明确提到它的LinkedList:
列表中元素的顺序与顺序相同 提供参数,或提供的数组中的元素。
答案 0 :(得分:9)
但是,目前还不清楚返回对象的具体类型。
这是所有你需要知道的!重点是:这些方法确实在目的上返回了一些List<Whatever>
。你得到的东西是保证来履行List接口所表示的公共合同。它是给出该方法的东西的列表,其顺序与写下来的顺序相同。
你绝对应该避免编写任何代码,这些代码需要知道 more 这些方法返回的列表!这是一个实现细节,它应该不对调用这些方法的客户端代码很重要!
从这个意义上说:您的关注点应该更多地放在客户端 - 例如,避免使用您在示例中使用的原始类型(使用List
而不使用特定的泛型类型)。
答案 1 :(得分:7)
List.of
返回的类是一个包私有静态类,因此不属于公共API:
package java.util;
...
class ImmutableCollections {
...
static final class List0<E> extends AbstractImmutableList<E> {
...
}
static final class List1<E> extends AbstractImmutableList<E> {
...
}
static final class List2<E> extends AbstractImmutableList<E> {
...
}
static final class ListN<E> extends AbstractImmutableList<E> {
...
}
}
所以这不是ArrayList(也不是LinkedList)。您需要知道的唯一事情是不可变并且满足List
接口合同。
答案 2 :(得分:4)
实际上,同样的想法是Collectors.toList
例如 - 你得到一个List
,文档特别说:There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned
。 目前返回了ArrayList
,但显然这可以随时更改。
我想知道是否应该在这里做同样的事情 - 明确提到类型是List
而已。这为将来的实施提供了很多理由,以决定最适合的类型 - 速度,空间等。
答案 3 :(得分:3)
List.of
会返回List
这样的特殊类型Collections.UnmodifiableList
。它既不是ArrayList
也不是LinkedList
。当您尝试修改它时会抛出异常。
答案 4 :(得分:3)
虽然@ZhekaKozlov和@GhostCat似乎已经回答了问题,但是返回类型(ImmutableCollections.List
)以及它是如何创建的包都是私有的,而不是公共API。还要说明这些工厂方法的实现保证了履行List接口所表示的公共合同。
进一步提供ImmutableCollections
实施的要点,然后设置,映射和列表中的一步。我会为List
添加一个示例表示,这与Map
和Set
非常相似。
ImmutableCollections
目前在接口List
上使用以下方法实现这些工厂方法:
abstract static class AbstractImmutableList<E>
扩展了AbstractList
类,并为覆盖其实现的所有可能操作抛出UnsupportedOperationException
。意味着不再允许对集合进行操作,使它们等同于Java Immutable Collections。
此外,这是通过类
扩展的static final class ListN<E> extends AbstractImmutableList<E>
使用构造函数来评估输入的某些检查及其元素为 NonNull 以返回由E[] elements
组成的对象(类型为元素的数组) E)并根据这些元素覆盖某些实现为.get(int idx)
,.contains(Object o)
。
Map and Set的方式类似,只是在那里确保了元素顶部的验证或一对键和值的验证。这样你就无法创建它们(分别抛出IllegalArgumentException和NullPointer异常):
Set<String> set2 = Set.of("a", "b", "a");
Map<String,String> map = Map.of("key1","value1","key1","value1");
Set<String> set2 = Set.of("a", null);
Map<String,String> map = Map.of("key1",null);