Arrays.asList() VS List.of()
使用场景:将一个引用类型数组转成List。
详解Arrays.asList()
Arrays.asList() 从 JDK1.2 开始支持。
// Arrays
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
// 这是 Arrays 的内部类 ArrayList,注意和 java.util.ArrayList 区分
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
}
// Objects
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Arrays.asList(1, 2, 3);
首先从这个方法的参数说起,是一个变长参数,可以接收单个参数,多个参数,或者是一个数组类型,但是要求这些参数的类型是一样的。或者说是继承关系。
流程:
- 创建一个内部类 Arrays.ArrayList,调用其构造方法。
- 构造方法是将内部类 Arrays.ArrayList 的成员变量 a 赋值为这个传入的数组。
成员变量 a 是 final 的,是一个不可变对象,也就是说不能将其引用指向其它数组了。本质是原始数组的视图。
支持元素的修改,但不支持结构的修改。(支持 set(),不支持 add()/remove())。
可以调用一下 add() 方法,发现 Arrays.ArrayList 本没有重写 add() 方法,使用的是父类 AbstractList 的 add() 方法,直接抛出 UnsupportedOperationException 异常。同样,remove() 也是一样的。
对于 set() 方法,Arrays.ArrayList 进行了重写。
对于 null 元素的支持,如果是一个引用类型数组,允许其中元素为 null,但是如果是直接使用单个 null 作为参数是不行的,因为会调用内部类的构造函数,然后在调用基类 Objects 的 requireNonNull,明显当为 null 会抛出空指针异常。
但是如果是两个 null 以上,会将其转换成数组类型,数组中的元素为 null,但是其并不是 null。
List<Integer> list = Arrays.asList(null); // NullPointerException List<Integer> list = Arrays.asList(null, null); // 正常
设计初衷:数组转列表的视图,减少内存拷贝(浅拷贝),适合临时只读/修改元素,不适合修改结构。如果要修改结构的话,可以直接使用 java.util.ArrayList。并且可以把 Arrays.ArrayList 当成一个中间列表,构造一个 java.util.ArrayList。
详解List.of()
List.of() 从 JDK9 开始支持。
返回的是一个 java.util.ImmutableCollections,一个不可变列表。明确指明了不支持添加、删除、修改元素操作。对于这些操作,在 AbstractImmutableList 中全部重写了,直接抛出不支持异常。
// all mutating methods throw UnsupportedOperationException
@Override public void add(int index, E element) { throw uoe(); }
@Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }
@Override public E remove(int index) { throw uoe(); }
@Override public void replaceAll(UnaryOperator<E> operator) { throw uoe(); }
@Override public E set(int index, E element) { throw uoe(); }
@Override public void sort(Comparator<? super E> c) { throw uoe(); }
Arrays.asList() VS List.of()
- 作用都是将一个引用数据类型数组转List
- Arrays.asList() 支持数组参数中元素为 null。List.of() 不支持数组参数中元素为null。
- Arrays.asList() 是浅拷贝。List.of() 并不是拷贝,底层是创建一个新的不可变列表,将数组参数的每个元素提出来到这个不可变列表中。
static <E> List<E> listFromArray(E... input) {
// copy and check manually to avoid TOCTOU
@SuppressWarnings("unchecked")
E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input
for (int i = 0; i < input.length; i++) {
tmp[i] = Objects.requireNonNull(input[i]);
}
return new ListN<>(tmp, false);
}
浙公网安备 33010602011771号