🎈 개요

위 코드에서 단순히 Member를 만들고, List에 담아 stream을 통해 뭔가 처리 한 뒤에 toList로 다시 변환한다.
변환된 List에 add를 하면 어떤 일이 발생할까?
보기에는 큰 문제가 없어 보인다. 하지만 jdk 17에서 어떤식으로 변화했는지 유심히 살펴보지 않았다면 큰 문제로 이어진다.
결론부터 보자면 아래와 같다. (java.lang.UnsupportedOperationException - UOE 발생!!!)

❓ 왜 이런걸까?

stream 인터페이스의 toList() 메소드를 확인해보자. default로 선언된 toList()는 기본적으로 Collections.unmodifiableList 을 호출하는데 불변리스트를 호출하는 것 이다.
그럼 해당 메소드의 호출 부분을 더 보자

여기서 살펴보면 파라미터로 전달된 list의 클래스가 UnmodifiableList.class 혹은 UnmodifiableRandomAccessList.class가 아니라면 RandomAccess 인터페이스를 상속하는지 여부에 따라 달라지는데 쉽게 말하자면 빠른(일반적으로 일정한 시간) 임의 액세스를 지원한다는 것을 나타내는지 여부를 판단한다.

즉, 우리가 일반적으로 사용하는 ArrayList 또한 RandomAccess에 포함되어 new UnmodifiableRandomAccessList(list) 가 반환된다.


그럼 UnmodifiableRandomAccessList 클래스를 extends 하는 UnmodifiableList를 보면 된다.
UnmodifiableList의 add를 확인해보자.

add외에도 해당 클래스 자체는 불변 리스트이기 때문에 수정, 삭제, 정렬 등의 동작을 막고있다.
jdk를 17로 설정하면 intellij에서 기존의 .collect(Collectors.toList()) 코드를 .toList()로 수정하라는 hint를 준다.
하지만 제대로 확인하고 설정해야 하니 주의하며 사용하자.
특히 버전이 올라가면서 동작이 달라지는 경우가 종종 있어서 평소에도 불변 클래스로 설계하는 연습이 필요할 것 같다.
List.of도 마찬가지로 불변 리스트를 return한다.
그럼 List.of로 생성한 리스트에 add를 하게 된다면 동일한 문제가 발생한다.
'Languege > Java & Spring' 카테고리의 다른 글
| [Swagger] Spring, Spring Boot 호환되는 버전 정리 (1) | 2025.07.08 |
|---|---|
| [Spring Transaction] TransactionManager 동작방식 (0) | 2025.01.24 |
| [String Constant Pool] Heap? PermGen? 오해와 진실 (1) | 2024.01.07 |
| Stream 사용법 (0) | 2023.11.15 |