Arrays.asList()方法
该方法的主要作用是将数组转换为List,但是其中还藏着许多的奥秘
注意事项:
- 该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean)
- 该方法将数组与列表链接起来,当更新其中之一时,另一个自动更新
- 不支持add和remove方法
对第一点进行演示
public class Test{
public static void main(String[] args) {
String[] s = {"aa","bb","cc"};
List<String> strlist = Arrays.asList(s);
for(String str:strlist){
System.out.println(str);
}
System.out.println("------------------------");
//基本数据类型结果打印为一个元素
int[] i ={11,22,33};
List intlist = Arrays.asList(i);
for(Object o:intlist){
System.out.println(o.toString());
}
System.out.println("------------------------");
Integer[] ob = {11,22,33};
List<Integer> oblist = Arrays.asList(ob);
for(int a:oblist){
System.out.println(a);
}
System.out.println("------------------------");
}
结果:
说明该方法无法将基本数据类型的数组转换为List
对第二点进行演示
public class Test{
public static void main(String[] args) {
String[] s = {"aa","bb","cc"};
List<String> strlist = Arrays.asList(s);
for(String str:strlist){
System.out.println(str);
}
System.out.println("------------------------");
//对list进行修改
strlist.set(1,"dd");
for(String str:s){
System.out.println(str);
}
System.out.println("------------------------");
//对数组进行修改
s[1]="pp";
for(String str:strlist){
System.out.println(str);
}
}
}
结果:
说明如果修改list或者数组的值都会使两个同步变化,注意:这里没有用add或remove
对第三点进行演示
public class Test{
public static void main(String[] args) {
String[] s = {"aa","bb","cc"};
List<String> strlist = Arrays.asList(s);
for(String str:strlist){
System.out.println(str);
}
System.out.println("------------------------");
//对list使用remove
strlist.remove(1);
for(String str:strlist){
System.out.println(str);
}
}
}
结果:
对22行报错
即strlist.remove(1)出错
也就是不能对该list进行remove,换成add也会是同样的结果
------------------------------------------------------下面是重点-------------------------------------------------------------
那么为什么会这样呢?明明大家都是list,凭什么他们都可以add、remove你为什么不行呢?搞特殊呢?
我们一层一层的去找原因,先看asList的代码
明明还是返回的是ArrayList啊,为啥不行呢?
我们接着往下走
这个时候我们到了这个地方,红圈内是上面方法的返回值
我把这个类中的代码全部展示出来
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public int size() {
return a.length;
}
@Override
public Object[] toArray() {
return Arrays.copyOf(a, a.length, Object[].class);
}
@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
@Override
public E get(int index) {
return a[index];
}
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
@Override
public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
@Override
public boolean contains(Object o) {
return indexOf(o) >= 0;
}
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(a, Spliterator.ORDERED);
}
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (E e : a) {
action.accept(e);
}
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
E[] a = this.a;
for (int i = 0; i < a.length; i++) {
a[i] = operator.apply(a[i]);
}
}
@Override
public void sort(Comparator<? super E> c) {
Arrays.sort(a, c);
}
@Override
public Iterator<E> iterator() {
return new ArrayItr<>(a);
}
}
不知道大家发现了没有,这个类里面是没有add和remove的,但是ArrayList继承了AbstractList类,让我们看看他的add和remove方法是怎么写的吧。
那正常ArrayList的add和remove方法是怎么写的呢?
可能有些同学会看不懂,但并不妨碍我判断这里的add和remove不一样,用asList生成的list他调用的是上面两条会抛出异常的方法,而普通的则调用的是下面的方法
至于为什么这么做,我认为是因为asList的第二点特性,以及数组的特性有关:
- 该方法将数组与列表链接起来,当更新其中之一时,另一个自动更新
- 数组空间不能增加会减少
因此,如果是asList()返回的ArrayList在调用add()或remove()的时候就会抛出UnsupportedOperationException的异常了