Arrays.aslist()方法详解(源码)

  1. Arrays里的asList()方法源码分析
  public static <T> List<T> asList(T... a) {
  		//创建一个ArrayList,该ArrayList是Arrays里的内部类,而不是java.util.ArrayList
        return new ArrayList<>(a);
    }
//该方法权限为private
private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;			//返回的数组是final修饰的,所以是不能修改的

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);						//判断传入的array对象是否为空
        }

        @Override
        public int size() {								
            return a.length;				//返回a数组长度
        }

        @Override
        public Object[] toArray() {
            return a.clone();				//将a数组强制类型转换为Object类型
        }

        @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) != -1;
        }

        @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);
        }
    }
  1. 首先说一个常见的坑,Arrays.asList(T)可以将数组转换为list,根据源码可以了解,转换过程中调用的ArrayList方法是Arrays的内部类,而不是java.util.ArrayList。所以只能使用Arrays里的ArrayList内部类里的方法,而且该方法返回的数组是一个final修饰的,所以方法返回的list不能增加删除,这也是Arrays类里的ArrayList里面没有add()和remove()方法的原因。转换后的list不能调用add()和remove()方法,但是list相关的其他方法都可以使用。如果继续使用add()或remove()方法,会报java.lang.UnsupportedOperationException不可操作异常。
public static void main(String[] args) {
        String[] str = {"a","b","c"};
        List<String> list = Arrays.asList(str);
        list.add("a");

    }
    //异常信息
Exception in thread "main" java.lang.UnsupportedOperationException
  1. 传入的参数必须为引用参数类型(源码分析)
 * @param <T> the class of the objects in the array				//这里对传入参数T有指明,传入的是数组里的元素class
     * @param a the array by which the list will be backed
     * @return a list view of the specified array
     */
    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

而传入基本数据类型的时候,由于int等基本数据类型不是对象,所以传入的时候,asList得到的是int数组对象本身,而不是int数组中的元素。

public static void main(String[] args) {
       int[] arr = {1,2,3};
        List<int[]> ints = Arrays.asList(arr);
        System.out.println(ints);
    }
//运行结果是int数组对象本身
[[I@7adf9f5f]

4.上述两个问题的解决办法

(1)Arrays.asList()方法生成的list不能调用add(),remove()方法

  • 把Arrays.asList()生成的list对象通过ArrayList创建一次,就可以使用java.util.ArrayList里的方法add()和remove()实现功能
 public static void main(String[] args) {
       String[] str = {"a","b","c"};
        List<String> list = Arrays.asList(str);
        //
        ArrayList<String> list1 = new ArrayList<>(list);
        list1.add("d");
        System.out.println(list1);
    }
    //运行结果
	[a, b, c, d]

(2)传入对象确保是引用数据类型,那样T获得的就是数组里的元素的class

public static void main(String[] args) {
      Integer[] integers = {1,2,3};
        List<Integer> integers1 = Arrays.asList(integers);
        System.out.println(integers1);
    }
    //运行结果
    [1, 2, 3]

版权声明:本文为qq_40389276原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。