불변 객체는 이름 그대로, 한번 생성되면 그 내부 값을 변경할 수 없는 객체를 의미한다.
이렇게 불변 객체에 대해서 어느 정도 이해했으면, 불변 컬렉션으로 넘어가겠다.
불변 컬렉션(Immutable Collection)은 컬렉션의 불변성을 보장하며 element를 추가/삭제할 수 없다.
단, 불변성은 컬렉션에만 해당하며 element의 참조나 내부 값은 변경할 수 있다.
import java.util.*;
class Person { ... }
public class Example {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice"));
people.add(new Person("Bob"));
// 불변 컬렉션 생성
List<Person> immutablePeople = Collections.unmodifiableList(people);
// 요소 추가/삭제 시도 → 예외 발생
// immutablePeople.add(new Person("Charlie")); // ❌ UnsupportedOperationException
// 요소 내부 값 변경 → 가능
immutablePeople.get(0).changeName("Eve"); // ✅ 가능
System.out.println(immutablePeople); // [Eve, Bob]
}
}
완전한 불변을 원한다면 요소 자체(위의 경우에서는 Person)도 immutable 객체로 만들어야 함.
(참고: https://dev-cool.tistory.com/23)
불변 컬렉션을 생성하는 데에는 보통 Collections.unmodifiableSet(), Set.of() 두 가지 방법을 사용한다.
Java 9 이전: Collections.unmodifiableSet()
Java 9 ~: Set.of()
주로 자바 버전에 따라 이렇게 쓰는 것 같다.
unmodifiableSet() 을 사용해 Immutable Collection을 만들기 위한 코드는 다음과 같다.
Set<String> set = new HastSet<>();
// ... add some elements in set
set = Collections.unmodifiableSet(set);
Set.of() 을 사용해 Immutable Collection을 만들기 위한 코드는 다음과 같다.
Set<String> set = Set.of("A", "B", "C"); // 변경 불가한 리스트
@GetMapping("/tags")
public ResponseEntity<List<String>> getTags() {
List<String> tags = tagService.findAllTags();
return ResponseEntity.ok(List.copyOf(tags));
}
List.copyOf(...)는 외부 리스트를 방어적으로 복사해 불변 리스트로 만든다.
public class Constants {
public static final List<String> REGIONS = List.of("서울", "부산", "제주");
}
public class UserDto {
private final List<String> roles;
public UserDto(List<String> roles) {
this.roles = List.copyOf(roles); // 방어적 복사
}
public List<String> getRoles() {
return roles;
}
}
| List.of() | 최대 10개 요소까지만 Map.of() 지원 (그 이상은 Map.ofEntries() 사용) |
| Null 불가 | List.of(null) → NullPointerException 발생 |
| 내부 데이터 수정 불가 | list.add(...), set.remove(...) 등 → UnsupportedOperationException 발생 |
| 컨트롤러 응답 반환 | ✅ List.copyOf() |
| 상수 설정 값 | ✅ List.of(...), Map.of(...) |
| 동적으로 값 추가/삭제 | ❌ ArrayList, HashMap 등 mutable 컬렉션 사용 |
| 멀티스레드 환경 | ✅ 데이터 공유 용도에 적합 |
+ 추가로 unmodifiable의 immutable 여부에 대해서는
참고하기.
참고:
- https://bibibim.tistory.com/17
- https://roomenergy.tistory.com/11
- https://sas-study.tistory.com/413
더 깊게 공부하기
- https://hello-judy-world.tistory.com/209