Collections.EMPTY_LIST는 사용할 때 주의를 해야 한다. 빈 껍데기 리스트를 생성하면서 add()는 호출하면 exception이 나는 구조이다.
@Test
public void test() {
// collections empty list
List<String> list = Collections.EMPTY_LIST;
try {
list.add("10");
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}
//guava empty list
List<String> myList = Lists.newArrayList();
try {
myList.add("10");
System.out.println("no exception in guava list");
} catch (UnsupportedOperationException e) {
e.printStackTrace();
}
}
guava의 Lists.newArrayList()는 ArrayList 구현체를 전달하는 반면,
Collections.EMPTY_LIST를 구현체가 있지만 add() 메소드를 구현하지 않았다.
따라서 위의 테스트 코드는 아래 에러가 발생한다.
java.lang.UnsupportedOperationException : null
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
..public class Collections { ... public static final List EMPTY_LIST = new EmptyList<>();
*/
private static class EmptyList<E>
extends AbstractList<E>
implements RandomAccess, Serializable {
private static final long serialVersionUID = 8842843931221139166L;
public Iterator<E> iterator() {
return emptyIterator();
}
public ListIterator<E> listIterator() {
return emptyListIterator();
}
public int size() {return 0;}
public boolean isEmpty() {return true;}
public boolean contains(Object obj) {return false;}
public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
public Object[] toArray() { return new Object[0]; }
public <T> T[] toArray(T[] a) {
if (a.length > 0)
a[0] = null;
return a;
}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
public boolean equals(Object o) {
return (o instanceof List) && ((List<?>)o).isEmpty();
}
public int hashCode() { return 1; }
@Override
public boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
return false;
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
}
@Override
public void sort(Comparator<? super E> c) {
}
// Override default methods in Collection
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
}
@Override
public Spliterator<E> spliterator() { return Spliterators.emptySpliterator(); }
// Preserves singleton property
private Object readResolve() {
return EMPTY_LIST;
}
}
따라서 모든 List는 add() operation을 구현하고 있다는 것을 가정할 수 없다. List 생성할 때는 항상 신중해야 겠다..
참고로..Collections.emptyList()도 동일하게 에러가 발생한다.
List list = Collections.emptyList();
list.add("11");
그 이유는 해당 메소드는 EMPTY_LIST를 그대로 리턴하기 때문이다.
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
'java core' 카테고리의 다른 글
[java8] DateTimeParseException - could not be parsed at index 3 (0) | 2015.05.20 |
---|---|
java8 & play1.3.0 migration (0) | 2015.05.18 |
Java 8 lamda / Comparator List Sort 예제 (0) | 2015.05.16 |
[java8-guava] Java7-Guava-FluentIterable vs Java8-Guava-FluentIterable 예제 (0) | 2015.05.10 |
[jvm runtime] Java 7 -> Java 8 Migration 주의 사항 (또는 Tip) (0) | 2015.03.18 |