ArrayList源码学习--构造方法篇

2021-02-05  本文已影响0人  SmileFH

ArrayList源码学习

成员变量解读

1. serialVersionUID成员变量:
  1. 代码

    /**
         * 这个UID主要是为了在ArrayList序列化的时候判断属性是否合格产生的<br/>
     * https://www.jianshu.com/p/91fa3d2ac892关于UID的详情可看这里,通俗易懂
     * 有点类似于版本控制的变量
     *
     * @author Hue Fu
     * @date 2021-01-31 10:42
     * @since 0.0.1
     */
    private static final long serialVersionUID = 8683452581122892189L;
    
  2. 解读

    1. Java serialVersionUID 有什么作用?

      1. 简单来说就是序列化和反序列化时候的标识符。在开发的时候我们一般用它来控制版本的兼容性,如果版本中这个对象的成员变量改变了,为了版本的向后兼容,或者不想让以前的版本来兼容它,就可以改变UID的值抛出一个InvalidClassExceptions异常。
    2. 序列化和反序列化有什么作用呢?

      1. 将对象编译为字节流数组,然后可以从jvm堆内存保存到共享内存中,从而可以保存到存储介质中去(磁盘)

      2. 网络传输,在传输的时候我们传输的都是字节流或者xml,序列化可以实现这个

      3. 序列化保存的是对象的状态,而不是类的状态,所以静态变量的内容和translate关键词修饰的变量没法序列化保存。

    3. 序列化的方式除了Serializable接口,还有什么呢?他们有什么区别呢

      1. TODO
2. DEFAULT_CAPACITY:默认容量
  1. 代码

    /**
     * 默认的初始化容量<br/>
     * Default initial capacity.
     *
     * @author Hue Fu
     * @date 2021-01-31 10:43
     * @since 0.0.1
     */
     private static final int DEFAULT_CAPACITY = 10;
    
  2. 解读

    1. 定义了一个默认的初始化容量,在ensureCapacity方法中被调用,这个方法最常被add方法给调用。
3. EMPTY_ELEMENTDATA:空元素数据数组
  1. 代码

    /**
     * Shared empty array instance used for empty instances.<br/>
     * 它就是个空数组实例,空的数组
     * @author Hue Fu
     * @date 2021-01-31 19:18
     * @since 0.0.1
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};
    
  2. 解读

    1. 这就是一个空数组罢了
4. DEFAULTCAPACITY_EMPTY_ELEMENTDATA:默认容量空元素数据数组
  1. 代码

    /**
     * ArrayList无参构造函数,构造的就是这个默认容量的空数组。<br/>
     * 用于默认的空数组实例对象构建,和EMPTY_ELEMENTDATA不一样<br/>
     * Shared empty array instance used for default sized empty instances. We<br/>
     * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when<br/>
     * first element is added.
     *
     * @author Hue Fu
     * @date 2021-01-31 19:21
     * @since 0.0.1
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    
  2. 解读

    1. 这是无参构造函数时赋值的底层数组
5. elementData:ArrayList的底层数组,几乎所有的方法都是对这玩意进行操作的
  1. 代码

    /**
     * ArrayList的底层数组实现就是通过这个任意类型的数组<br/>
     * transient关键字的作用是:阻止序列化对象中的不必要成员变量持久化<br/>
     * https://www.cnblogs.com/lanxuezaipiao/p/3369962.html细节可查阅这个<br/>
     * non-private to simplify nested class access,不声明为私有的原因是方便内部类调用<br/>
     *
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     *
     * @author Hue Fu
     * @date 2021-01-31 11:25
     * @since 0.0.1
     */
    transient Object[] elementData; // non-private to simplify nested class access
    
  2. 解读

    1. 这玩意就是ArrayList的底层基础啊,所有的方法操作都是对它进行的。
6. size:数组中包含的元素数量,不是数组的长度。元素数量和数组长度概念一定要分清楚。
  1. 代码

    /**
     * 注意这里的size表示的是数组中的元素数量,null元素和空元素可是不一样的呦,如果一个<br/>
     * 元素被标记为null那么它也是占有一个空间大小的,也就是说null元素也会占用一个size大小<br/>
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     *
     * @author Hue Fu
     * @date 2021-01-31 11:27
     * @since 0.0.1
     */
    private int size;
    
  2. 解读

    1. 这个变量一直存放着当前数组中的元素总个数呢。

构造方法解读

1. 无参构造
  1. 代码

    /**
    * Constructs an empty list with an initial capacity of ten.
    */
    public ArrayList() {
       this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    
  2. 解读

    1. this.elementData:是ArrayList操作的底层数组。

    2. DEFAULTCAPACITY_EMPTY_ELEMENTDATA:静态创建的一个final空数组。成员变量部分有介绍。

2. 单参构造-初始化数组大小
  1. 代码

    /**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
    
  2. 解读

    1. initialCapacity:指定容量大小

    2. 为啥先判断容量大于0的了?

      1. 创建大于0数组的概率大啊

      2. 写代码的时候很少是需要创建一个长度为0的数组的,再不济也是空参啊,没事儿传个0干啥,脱裤子放屁--多此一举。但是作为程序员这种情况也是要考虑到的。

      3. 如果传入的是一个<0的数字,那么最后会抛出一个非法操作的异常,说你传入的初始容量是不正确的。

3. 单参构造-传个继承了Collection接口实现的对象
  1. 代码

    /**
     * Constructs a list containing the elements of the specified
     * collection, in the order they are returned by the collection's
     * iterator.
     *
     * @param c the collection whose elements are to be placed into this list
     * @throws NullPointerException if the specified collection is null
     */
    public ArrayList(Collection<? extends E> c) {
        Object[] a = c.toArray();
        if ((size = a.length) != 0) {
            if (c.getClass() == ArrayList.class) {
                elementData = a;
            } else {
                elementData = Arrays.copyOf(a, size, Object[].class);
            }
        } else {
            // replace with empty array.
            elementData = EMPTY_ELEMENTDATA;
        }
    }
    
  2. 解读

    1. 传入的是一个实现了继承Collection接口的实体类,比如:SetList的实体类
上一篇 下一篇

猜你喜欢

热点阅读