정의
- 생성 후 그 상태를 변경할 수 없는 객체를 의미함
- 불변 객체는 프로그램의 안정성을 높이고 예측 가능한 코드를 작성하는 데 도움이 됨
- 특히, 멀티스레드 환경에서는 동시 접근 시 상태 변화가 없어 안전하게 사용할 수 있어 유용함
예시
자바에서 불변 객체를 만드는 대표적인 방법은 final 키워드를 사용하는 것
String 클래스가 대표적인 불변 클래스임
public final class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } // Getter만 제공, Setter는 제공하지 않음 public String getName() { return name; } public int getAge() { return age; } }자바에서 많이 쓰이는 불변 클래스들은 다음과 같음
클래스 설명 String 문자열의 내용을 변경할 수 없기 때문에, 새로운 문자열이 생성될 때마다 새로운 객체가 만들어짐 Wrapper 클래스 Integer, Double, Boolean 등 자바의 기본 타입을 감싸는 클래스들은 모두 불변 객체 LocalDate, LocalDateTime Java에서 날짜와 시간 API의 대부분 객체는 불변 객체로 설계되어 있어 안정성이 높음
특징과 장점, 주의점
1. 특징
1. 초기화 후 상태 변경 불가
- 객체가 생성된 이후에는 내부 상태가 절대 바뀌지 않음
2. 방어적 복사
- 객체 생성 시 전달받은 객체의 방어적 복사(defensive copy)를 통해 외부에서 객체 상태를 바꿀 수 없게 함
3. 쓰레드 안정성(Thread-Safe)
- 상태가 변하지 않으므로 동기화 없이 여러 스레드에서 안전하게 접근할 수 있음
2. 장점
1. 동시성 문제 해결
- 불변 객체는 스레드 간 공유에 있어 동기화 없이 안전하게 사용할 수 있어 동시성 문제가 줄어듦
2. 안정성
객체의 상태가 변경되지 않아 예측 가능한 동작을 수행
3. 의도 명확성
상태가 변하지 않기 때문에 코드를 읽을 때 그 의도를 명확하게 파악할 수 있음
3. 주의점
- 불변 객체는 많은 장점이 있지만 불필요한 객체 생성이 발생할 수 있음
- 값이 자주 바뀌어야 하는 경우라면 가변 객체를 사용하는 것이 성능에 더 유리할 수 있음
👉 불변 객체를 사용할지, 가변 객체를 사용할지 상황에 맞게 선택하는 것이 중요함
생성법
1. 클래스를 final로 선언하여 상속을 막음
2. 모든 필드를 final로 선언하여 값 변경을 방지
3. Setter 메서드를 제공하지 않음으로써 외부에서 필드 값을 수정할 수 없게 함
4. 방어적 복사
- 만약 필드가 객체 참조를 포함하는 경우, 해당 객체를 복사하여 반환함으로써 외부에서 객체의 상태를 변경하지 못하도록 함
예를 들어, 필드가 List일 경우 방어적 복사를 구현할 수 있음
public final class ImmutablePerson { private final String name; private final List<String> hobbies; public ImmutablePerson(String name, List<String> hobbies) { this.name = name; this.hobbies = new ArrayList<>(hobbies); // 방어적 복사 } public String getName() { return name; } public List<String> getHobbies() { return new ArrayList<>(hobbies); // 방어적 복사 } }
비고
1. 불변 객체 관련 복사 방지 예외 때문에 찾아보면서 정리가 많이 되었다.
레퍼런스
1. 멘토링 강의
2. 구글링, 코드 예시의 경우 ChatGPT
'개발지식 조각 > Java' 카테고리의 다른 글
| 런타임 예외와 Unchecked Exception (0) | 2024.10.31 |
|---|---|
| 추상클래스와 메서드 (0) | 2024.10.31 |
| 함수와 메서드의 차이 (0) | 2024.10.25 |
| [Java] IllegalArgumentException (0) | 2024.10.23 |
| 오버라이딩(Overriding) (0) | 2024.10.23 |