본문 바로가기
Java, Kotlin

Collections.emptyList() cause UnsupportedOperationException

by 조니 Johnny 2022. 11. 3.

안녕하세요. 오늘은 제 부주의로 겪은 Exception에 대해 회고하려 합니다.

진짜 지금 보면 어이없는 에러지만, 자주 Collections.emptyList() 마주치는 사람들에게는 도움이 되길 바랍니다.

 

테스트 코드

바로 테스트코드를 살펴보겠습니다.

@Test
void collectionsEmptyListCauseException(){
    List<String> list = new ArrayList<>();
    list.add("johnny is flo developer");

    List<String> emptyList = Collections.emptyList();

    assertThrows(UnsupportedOperationException.class, () -> {
        for (int i=0; i<2; i++){
            list.add("yes he is");
            emptyList.add("yes he is");
        }
    });
}

IntelliJ를 쓰시는 분들은 이 코드를 붙여넣기 하자마자 이상함을 느끼신 분들이 있을겁니다. (IntelliJ는 똑똑하게 문제가 되는 라인에 warn 을 주거든요. 근데 실무에서는 워낙 복잡한 코드들이 많아서 이것마저 지나칠 수 있습니다. 바로 제가 그렇습니다.)

타입은 ArrayList, EmptyList 둘 다 List 로써 타입 캐스팅이 가능합니다. 그래서 아무 문제 없다고 생각하고(간과하고) 넘어가는 경우가 많은데요. 🥲

테스트 코드에서 보이시다 싶이 EmptyList는 ArrayList와 다르게 UnsupportedOperationException을 일으킵니다. 이유를 한번 간단하게 짚고 넘어가보겠습니다.

 

원인 분석

java.util.ArrayList
java.util.EmptyList

여기서 잘 살펴야 하는 부분이 두 객체 모두 extends AbstractList 한다는 점인데요.

AbstractList.class는 멤버로써 .add()라는 메소드를 가집니다. 좀더 자세히 살펴보겠습니다.

java.util.AbstractList

AbstractList.class / .add() 메소드의 노트(Note)는 다음과 같이 말합니다. "아래 구현은 .add(int, E)를 재정의 하지 않는 이상 UnsupportedOperationException을 발생시킨다." 또한 UnsupportedOperationException 을 발생시키는 doc을 참고하면 "add operation이 지원되지 않는 리스트에서 발생시킨다." 라고 알려줍니다. 

 

결론

둘 다(ArrayList, EmptyList) extends AbstractList 하여 AbstractList의 .add() 메소드 자체는 사용 가능하다. 그래서 compile 시점의 checked error로 발생시키지는 않지만. java.util.EmptyList에서 .add() 메소드에 대한 별다른 구현(암묵적 Unsupported)이 없었기에 UnsupportedOperationException (RuntimeException)이 발생한 것입니다.

 

마무리

읽어주셔서 감사합니다 🙇🏻‍♂️

댓글