欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA两个空数组的区别

程序员文章站 2022-05-12 11:26:32
...

EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA两个都是ArrayList的成员变量,并且都被声明为static final;更为核心的是,这两个都是空数组,那么问题来了,为什么要这样去规范呢?

对于这类问题,直接看:

    /**
     * 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);
        }
    }

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

    /**
     * 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) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

直接看源码,可以看到的是,ArrayList有三个构造函数:

无参构造:

无参构造时,Obeject数组elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

当其为有参构造时:会有两种情况:

给定初始容量构造:

源码具体逻辑如下:
当 传入的初始容量initialCapacity > 0为真时,创建一个大小为initialCapacity的空数组,并将引用赋给elementData;

当 传入的初始容量initialCapacity = 0为真时,将空数组EMPTY_ELEMENTDATA赋给elementData;

当 传入的初始容量initialCapacity < 0为真时,直接抛出IllegalArgumentException异常。

集合类中进行构造:

这里只需要知道的一个就是如果传入结合为空,那么将空数组EMPTY_ELEMENTDATA赋给elementData;

从上面几个可以总结出来的就是:

当无参构造时,Obeject数组elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;

当有参构造时,如果给定初始容量为0,或者传入集合为空集合(不是null),那么,将空数组EMPTY_ELEMENTDATA赋给elementData;

这就是这两个空数组唯一的区别了,这是jdk8的源码,两者个人感觉只是为了对某些东西和状态加以标记和区分,比如说扩容的时候,其实,在jdk7的时候,ArrayList的源码是这样的:

public ArrayList(int initialCapacity) {
    super();
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal Capacity: "+
                initialCapacity);
    this.elementData = new Object[initialCapacity];
}
 
public ArrayList() {
    super();
    this.elementData = EMPTY_ELEMENTDATA;
}
 
public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    size = elementData.length;
    // c.toArray might (incorrectly) not return Object[] (see 6260652)
    if (elementData.getClass() != Object[].class)
        elementData = Arrays.copyOf(elementData, size, Object[].class);

对比可以看到的是差不多可以说jdk8的DEFAULTCAPACITY_EMPTY_ELEMENTDATA 代替了jdk7的EMPTY_ELEMENTDATA。有区别的一点是jdk8中EMPTY_ELEMENTDATA作用改变了,从构造函数源码中 可以看到,如果给定初始容量为0,或者传入集合为空集合(不是null),那么,将空数组EMPTY_ELEMENTDATA赋给elementData。而在Java7中如果容量是0的话,会创建一个空数组,赋值给elementData。这里可以知道jdk8的EMPTY_ELEMENTDATA在一定程度上减少了空数组的存在,降低内存的消耗,一定程度上是对性能的优化。对比jdk7,才更能感受到这两者的一点区别。

相关标签: ArrayList底层