[Java] List.of()와 Arrays.asList() 차이

문제

List에 데이터를 추가할 때, null값 그 자체를 추가해야 하는데 NPE 에러가 발생했다.

List.of() 메서드를 이용해 List를 만들어주었는데 List.of() 메서드는 null 요소를 허용하지 않기 때문에 발생한 문제였다.

 

해결

해결은 간단히 List.of() 메서드 대신 Arrays.asList() 메서드를 사용하는것으로 변경하여 문제를 해결 할 수 있었는데, 이 둘의 차이가 무엇인지 알아보자.

 

List.of() vs Arrays.asList()

List.of()

우선 List.of() 메서드는 자바9 버전 이후에 도입된 메서드로 파라미터로 전달받은 값들을 불변 리스트로 만드는 역할을 한다.

 

그리고 요소 하나하나 null인지 Objects.requireNonNull()메서드로 검사를 한다. 그래서 나의 경우 NPE 에러가 발생했었다.

또한 List.of()로 생성된 List는 ImmutableCollections 클래스에서, AbstractImmutableList를 상속하고 있는 List12라는 inner class이다. 즉, 우리가 알고있는 ArrayList의 구현체가 아니다.

 

불변 리스트로 생성했기 때문에 add(), addAll(), remove(), replaceAll(), set(), sort() 메서드를 사용하면  UnsupportedOperationException 에러가 발생한다.

그 이유가 AbstractImmutableList 추상 클래스를 보면 add(), addAll(), remove(), replaceAll(), set(), sort() 을 오버라이드해 강제로 에러를 던지게 하고 있기 때문이다.

 

Arrays.asList()

반면 Arrays.asList()로 생성한 리스트는 인자로 null값을 전달해도 NPE가 발생하지 않고 리스트를 생선한다.

그 이유는 List.of()와 다르게 리스트를 생성할때 파라미터로 전달받은 인자 하나하나 null 값인지 검사하지 않고 전달받은 값 자체가 null인지만 확인하기 때문이다.

 

그리고 List.of() 메서드 처럼 add(), addAll(), remove() 메서드를 사용하면 UnsupportedOperationException 에러가 발생하지만, set(), replaceAll(), sort() 메서드는 사용이 가능하다.

 

그 이유는 Arrays.asList()로 생성한 리스트 역시 우리가 알고 있는 ArrayList 클래스의 구현체가 아닌 Arrays 클래스의 inner 클래스인 ArrayList 클래스이고, 이 클래스가 set(), repalceAll(), sort() 메서드를 오버라이드하여 사용하고 있기 때문이다.

 

즉, Arrays.asList() 로 생성한 리스트는 요소 추가나 삭제는 되지 않지만 변경이 가능하기 때문에 불변이라고 볼 수 없다.

완전한 불변인 List.of()로 리스트를 생성해서 사용하는게 권장되는 방식이지만, 요소 하나하나 null을 검사하기 때문에 나의 상황에서는 List.of() 대신 Arrays.asList() 메서드를 사용해야 했다.