背景
项目中有时候会使用Collections.emptyList返回一个空列表,但是emptyList在执行add,remove等方法时会直接抛出UnsupportedOperationException异常,我们可以看下源码
public class Collections {
public static final List EMPTY_LIST = new EmptyList<>();
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
private static class EmptyList<E>
extends AbstractList<E>
implements RandomAccess, Serializable {
public int size() {return 0;}
public boolean isEmpty() {return true;}
public boolean contains(Object obj) {return false;}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
}
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
}
我们可以发现emptyList最后执行的是AbstractList里面的add方法,所以会直接抛出异常。为了避免报错,有同事提议将emptyList都用new ArrayList()代替,此时决定看下emptyList的优势
代码
通过百度知道emptyList不需要占用内存,而ArrayList每次new都会在堆中开辟内存空间存放对象,我们先通过代码验证一下
public class ListTest {
private static final int printCount = 10000;
public static void main(String[] args) {
long freeMemory = Runtime.getRuntime().freeMemory();
System.out.println("freeMemory: " + freeMemory);
for (int i = 0; i < printCount; i++) {
List newList = new ArrayList();
}
long freeMemoryNew=Runtime.getRuntime().freeMemory();
System.out.println("freeMemory use: "+(freeMemory-freeMemoryNew));
for(int i = 0;i < printCount; i++){
List emptyList = Collections.emptyList();
}
long freeMemoryEmpty = Runtime.getRuntime().freeMemory();
System.out.println("freeMemory use: "+(freeMemoryNew-freeMemoryEmpty));
}
}
此时我们看一下执行结果
Connected to the target VM, address: '127.0.0.1:63534', transport: 'socket'
Disconnected from the target VM, address: '127.0.0.1:63534', transport: 'socket'
freeMemory: 253398816
freeMemory use: 1430376
freeMemory use: 0
Process finished with exit code 0
我们可以看出new ArrayList执行一万次会消耗1430376KB内存,而Collections.emptyList不会消耗内存,那有人会说emptyList不也是new EmptyList()吗?其实我们再仔细看下上面的源码就发现emptyList是一个static变量,只会初始化一次,所以后续使用不会再初始化对象。此时我们可以得出结论,emptyList不占用内存,但是无法执行add等方法,new ArrayList()占用内存,但是会初始化对象数组,可以执行add等方法。
网友评论