EMPTY_ELEMENTDATA和DEFAULTCAPACITY_EMPTY_ELEMENTDATA两个空数组的区别
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,才更能感受到这两者的一点区别。