java中的Arrays.asList()浅析

1.Arrays.asList(T..)使用的是静态内部类:ArrayList, (没有定义add和remove等一些方法),而不是java.util.ArrayList

/**
     * 1.测试Arrays.asList()方法 
     * @author zhangdi
     * @description 
     * 使用的是静态内部类:ArrayList, (没有定义add和remove等一些方法),而不是java.util.ArrayList
     * 接受的参数被一个final修饰的成员变量 private final E[] a接受
     * 调用Arrays.asList()的add和remove方法 会抛异常:java.lang.UnsupportedOperationException
     */
    @Test
    public void testAsListOfArray() {
        List<String> list = Arrays.asList("1", "2", "3");
        list.add("4");
        for (String string : list) {
            System.out.println("string:" + string);
        }
    }

    @Test
    public void testAsListOfArray2() {
        List<String> list = new ArrayList<>();
        list.add("5");
        list.add("6");
        list.add("7");
        list.add("8");
        for (String string : list) {
            System.out.println("string:" + string);
        }
    }

2.为什么List<int[]> asList2 = Arrays.asList(d);返回的是List<int[]>而不是List<int>呢?为什么testAsListOfArray3中的list.size():输出1而不是4呢?

/**
     *  2.Array.asList()接收基本类型与单个元素
     *  @author zhangdi
     *  @see https://stackoverflow.com/questions/1467913/arrays-aslist-not-working-as-it-should
     */
    @Test
    public void testAsListOfArray3(){
        //1
        int[] f = {1,2,3,4};
        List list = Arrays.asList(f);
        System.out.println("list.size():"+list.size());  //output: list.size():1

        //2
        int[] a = {1,2,3,4,8,10,22,12,214,23};  
        String[] b = {"a","b","c"};  
        Integer[] c = {1,2,3,4,8,10,22,12,214,23};
        System.out.println(Arrays.asList(a));  
        System.out.println(Arrays.asList(b));  
        System.out.println(Arrays.asList(c)); 

        //3
        //There's no such thing as a List<int> in Java - generics don't support primitives.
        //Autoboxing only happens for a single element, not for arrays of primitives.
        //java arrays are objects and Arrays.asList() treats your int array as a single argument in the varargs list.
        int[] d = new int[]{1,2,3,4,8,10,22,12,214,23};  
        Integer[] e = new Integer[]{1,2,3,4,8,10,22,12,214,23}; //避免使用原始类型数组作为asList的输入参数
        List<int[]> asList2 = Arrays.asList(d);
        List<Integer> asList3 = Arrays.asList(e);
        System.out.println(asList2);  
        System.out.println(asList3);  
       // output:
        /*
        1
        [[I@232d49d1]    //会被当做一个参数接收
        [a, b, c]
        [1, 2, 3, 4, 8, 10, 22, 12, 214, 23]
        [[I@ef05133d]
        [1, 2, 3, 4, 8, 10, 22, 12, 214, 23]
        */
    }

因为:Arrays.asList()方法接受一个可变参数T,一般可看做数组参数,但是因为int[] 本身就是一个类型,所以a变量作为参数传递时,编译器认为只传了一个变量,这个变量的类型是int数组,所以size为1,相当于是List中数组的个数。基本类型是不能作为泛型的参数,要想作为泛型化参数就必须使用其对应的包装类型。 按道理此处应该使用包装类型,但这里却没有报错,因为数组是可以泛型化的,所以转换后在list中就有一个类型为int的数组; 所以 ,以后要避免使用原始类型数组作为asList的输入参数.

另外,java8的一些写法:学习一下

//1
Integer[] boxedInts = IntStream.of(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedInts = IntStream.of(ints).boxed().collect(Collectors.toList());
//2
Integer[] boxedIntArray = Arrays.stream(ints).boxed().toArray(Integer[]::new);
List<Integer> boxedIntList = Arrays.stream(ints).boxed().collect(Collectors.toList());
  1. 自己实现一个asList方法,能够add和remove; (比较一下自己和源码的写法)
    /**
     * @author zhangdi
     * @param strings
     * @return  目的也是为了让返回的list是一个可操作的list
     * @description   jdk 中Arrays.asList()是一个静态方法: 
     */
    @SafeVarargs
    private static <T> List<T> asList(T... args) {
        List<T> list = new ArrayList<>();
        for (T a : args) {
            list.add(a);
        }
        return list;
    }

Arrays.asList()的手写第二个版本(目的也是为了让返回的list是一个可操作的list):

    /**
     * @author zhangdi
     * @param a
     * @return
     * @description asList_v2 比用for更为简洁
     */
    @SafeVarargs
    public static <T> List<T> asList_v2(T... a) {  
        List<T> list = new ArrayList<T>();  
        Collections.addAll(list, a);  
        return list;  
    }  

实际上,addAll底层用的也是for循环,还有一个 result |= c.add(element);操作,可以学习一下

    /**
     * jdk_source:
     * 把所有指定元素添加到集合c中, 有一个元素添加成功就返回true 
     */  
    public static <T> boolean addAll(Collection<? super T> c, T... elements) {  
        boolean result = false;  
        for (T element : elements)  
            result |= c.add(element);  
        return result;  
    } 

jdk源码 – Arrays.asList(T… a) :
从这个内部类ArrayList的实现可以看出,它继承了类AbstractList,但是没有重写add和remove方法,没有给出具体的实现。查看一下AbstractList类中对add和remove方法的定义,如果一个list不支持add和remove就会抛出UnsupportedOperationException。

    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    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 a.clone();
        }

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

参考:
https://stackoverflow.com/questions/1467913/arrays-aslist-not-working-as-it-should
https://blog.csdn.net/bruce128/article/details/21640479

原文地址:https://www.cnblogs.com/DiZhang/p/12545010.html