List.of()
不可以使用.set
方法改变指定下标的值,Arrays.asList()
可以
List<String> listOf = List.of("a", "b", "c");
List<String> arrayAs = Arrays.asList("a", "b", "c");
listOf.set(0, "e");//会报UnsupportedOperationException
arrayAs.set(0, "e");//成功修改
都不可以使用.add
方法
listOf.add("e");//会报UnsupportedOperationException
arrayAs.add("e");//会报UnsupportedOperationException
都不可使用.remove
方法
arrayAs.remove("a");//会报UnsupportedOperationException
listOf.remove("a");//会报UnsupportedOperationException
都不可使用.clear
方法
arrayAs.clear();//会报UnsupportedOperationException
listOf.clear();//会报UnsupportedOperationException
List.of()
不可以插入空值,Arrays.asList()
可以
List<String> listOf = List.of("a", "b", "c", null, null);//会报NullPointerException
List<String> arrayAs = Arrays.asList("a", "b", "c", null, null);//成功创建
List.of()
不可以使用contains
方法检验是否存在空值,Arrays.asList()
可以
System.out.println(arrayAs.contains(null));
System.out.println(listOf.contains(null));//会报NullPointerException
数组修改对List.of()
生成的List无影响,对Arrays.asList()
生成的List有影响
String[] arr = new String[]{"a","b","c"};
List<String> listOf = List.of(arr);
List<String> arrayAs = Arrays.asList(arr);
arr[0] = "e";
System.out.println("--------listOf-----------");
listOf.forEach(System.out::println);
System.out.println("--------arrayAs-----------");
arrayAs.forEach(System.out::println);
输出结果为:
--------listOf-----------
a
b
c
--------arrayAs-----------
e
b
c
List.of()
分析:下面截取的源码是以List
为例的,可以看出是将arr
中的元素循环遍历出来,循环将值放入新new出的数组中E[] tmp = (E[])new Object[input.length]
,循环遍历过程中会对值进行判空,若为空则会抛出异常throw new NullPointerException();
,这也就是为什么List.of()
不能插入空值的原因。再继续看把元素循环放入新数组后赋值给了elements
返回,而elements
的定义是private final E[] elements;
用final
修饰的,用final
修饰的变量是不可变的,直至变量被销毁。
@SafeVarargs
@SuppressWarnings("varargs")
static <E> List<E> of(E... elements) {
switch (elements.length) { // implicit null check of elements
case 0:
return ImmutableCollections.emptyList();
case 1:
return new ImmutableCollections.List12<>(elements[0]);
case 2:
return new ImmutableCollections.List12<>(elements[0], elements[1]);
default:
return new ImmutableCollections.ListN<>(elements);
}
}
/********************************************************************/
//ImmutableCollections.ListN<>(elements)方法点进去
@SafeVarargs
ListN(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]);
}
elements = tmp;
}
/********************************************************************/
//Objects.requireNonNull(input[i])方法点进去
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
/********************************************************************/
//返回值elements是用final修饰的
@Stable
private final E[] elements;
因此使用List.of()
创建的数组不可使用.set
、.add
、.remove
、.clear
这些修改变量的函数,你会发现这些函数是可以被调用到的,编译也是通过的,但运行起来却是报错的,以.set
为例看源码,可以看出来函数里面就做了一个抛异常的操作throw new UnsupportedOperationException();
。
public E set(int index, E element) {
throw new UnsupportedOperationException();
}
Arrays.asList()
分析:下面截取的源码是以List
为例的(以List
为例点进去源码也是一样的),可以看到用此方法生成的集合底层其实是数组,返回集合的底层其实就是传入的数组,只会校验传入的arr
是否为空,只要整个数组非空,就不会抛出异常,不会对里面的值进行校验,这就是Arrays.asList()
可以插入空值的原因,可以看到返回的a
值也是由final
修饰的,也是不可变的。
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
/********************************************************************/
//new ArrayList<>(a)方法点进去
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
/********************************************************************/
//Objects.requireNonNull(array)方法点进去
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
/********************************************************************/
//返回的a是用final修饰的
private final E[] a;
可以使用arr[0] = "e";
修改集合的值,这个不难理解,因为用此方法生成的集合底层就是传入的数组,但是为什么可以使用.set
修改集合呢,看下面源码,可以看出.set
方法里面依旧操作的是数组,so可以成功啦。
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
对于.add
、.remove
、.clear
这些方法都是不行的,会报错UnsupportedOperationException
,毕竟返回值a
是被final
修饰的private final E[] a;
,是不能够被改变的,而这些操作会改变集合的.size
属性,so是会报错的。