• java.util.ArrayList与java.util.Arrays$ArrayList区别


    本博客转载自:https://blog.csdn.net/maywehe/article/details/52553954

    写demo的时候,为了避免用list.add方法,特意写了个数组然后转换成list。一开始以为转换成的list就是实现了AbstractList的通用的List, 比如ArrayList或者LinkedList等。 当调用add方法的时候, 奇怪的事情发生了。

    String[] arrays = new String[] { "1", "2", "3" };
    List<String> list = Arrays.asList(arrays);
    list.add("4");
    

      抛异常:

    Exception in thread "main" java.lang.UnsupportedOperationException
        at java.util.AbstractList.add(AbstractList.java:148)
        at java.util.AbstractList.add(AbstractList.java:108)
        at com.maywe.list.Demo.main(Demo.java:43)
    

      

    List 调用add方法是最普遍不过的场景,怎么会抛异常呢? 赶快去研究下源码。

    java.util.Arrays$ArrayList 源码($表示内部类的意思,下面的源码是Arrays内部类ArrayList 的类型定义源码,在java.util.Arrays.class文件中

    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) {
                if (array==null)
                    throw new NullPointerException();
                a = array;
            }
    
            public int size() {
                return a.length;
            }
    
            public Object[] toArray() {
                return a.clone();
            }
    
            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;
            }
    
            public E get(int index) {
                return a[index];
            }
    
            public E set(int index, E element) {
                E oldValue = a[index];
                a[index] = element;
                return oldValue;
            }
    
            public int indexOf(Object o) {
                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;
            }
    
            public boolean contains(Object o) {
                return indexOf(o) != -1;
            }
        }

     

    的确是实现了AbstractList,但是没有实现add方法, 在看看AbstractList的add方法:

    public boolean add(E e) {
            add(size(), e);
            return true;
        }
    
    public void add(int index, E element) {
            throw new UnsupportedOperationException();
        }

    UnsupportedOperationException 就是怎么抛出来的。(解释:List<String> list = Arrays.asList(arrays)语句中,Arrays.asList(arrays)的返回值(Arrays$ArrayList类型)被向上为list。当调用add(E e)方法的时候,会直接调用Arrays$ArrayList类的add(int index, E element)方法,由于Arrays$ArrayList类没有重写add(size(), e)方法,所以会调用基类(AbstractList)的add(int index, E element)方法,所以会抛出UnsupportedOperationException异常。由此可知,如果想不报异常,Arrays$ArrayList类应该重写add(E e)方法或者add(int index, E element)方法

    所以java.util.Arrays$ArrayList只能在不超过capacity的情况下调用set设置元素,不能增加元素。


    顺便研究了下java.util..ArrayList的add方法。

    public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
        }

    在List的最后Append新元素,capacity增加一个

    public void add(int index, E element) {
            rangeCheckForAdd(index);//判断index是否小于0或者大于数组长度,
    
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);
            elementData[index] = element;
            size++;
        }
    • 在index指定的位置增加元素E, 同时index右边的(索引>index) 所有元素右移;
    • 如果参数index大于当前的size会抛出异常,因为capacity只是增加一;
    • 因为存在“右移”操作,建议没有必要的情况下调用List#add(E e)即可,避免不必要的“右移”操作

         demo 代码:

    String[] arrays = new String[] { "1", "2", "3" };
    List<String> list = Arrays.asList(arrays);
    System.out.println(list);
    System.out.println(list.getClass());
    List<String> list2 = new ArrayList<String>(list);
    list2.add(0, "0");
    System.out.println(list2);
    System.out.println(list2.getClass());

    结果输出:

    [1, 2, 3]
    class java.util.Arrays$ArrayList
    [0, 1, 2, 3]
    class java.util.ArrayList
  • 相关阅读:
    CI框架源码解析十九之分页类文件Pagination.php
    sublime新代码段
    sublime
    递归调用详解,分析递归调用的详细过程
    什么是锚点?锚点应该如何用?
    PHP中spl_autoload_register函数的用法
    PHP 构造方法 __construct()
    工欲善其事,必先利其器---IDE使用
    Apache操作
    js中常用的操作
  • 原文地址:https://www.cnblogs.com/yidaijiankuanzhongbuhui/p/9108148.html
Copyright © 2020-2023  润新知