1. 불변 객체란 무엇일까?
불변 객체는 객체의 상태(내부의 값, 필드, 멤버 변수)가 변하지 않는 객체로 한 번 초기화 후 수정될 수 없기 때문에 예측 가능하고 안전한 코드 작성을 할 수 있게 도와줍니다. 대표적으로 자바의 String, Integer 등의 클래스가 불변으로 설계되어 있습니다.
지금부터는 불변 객체의 장점과 불변 객체를 구현하는 방법에 대해 알아보겠습니다.
2. 불변 객체의 장점
스레드 안정성(Thread Safety)
멀티스레드 환경에서 가변 객체를 여러 스레드가 동시에 수정하려 할 때 동기화를 적절히 처리하지 않으면 예상치 못한 동작이 발생할 수 있습니다. 하지만 불변객체는 상태가 변하지 않으므로 스레드 안정성을 보장할 수 있습니다.
Side Effect를 최소화할 수 있다.
객체의 공유 참조는 막을 수 없습니다. 그래서 객체의 값을 변경하면 다른 곳에서 참조하는 변수의 값도 함께 변경되는 사이드 이펙트가 발생할 수 있습니다. 불변 객체는 값을 변경할 수 없기 때문에 사이드 이펙트가 원천 차단되고 코드의 예측 가능성과 안정성을 높일 수 있습니다.
실패 원자성
가변 객체는 연산 중간에 예외가 발생하면 객체의 상태가 불완전하게 변경될 수 있습니다. 반면, 불변 객체는 예외 발생 시 객체의 상태가 변하지 않으므로, 연산이 중단되더라도 이전 상태가 그대로 유지되어 안정성을 보장할 수 있습니다.
캐싱(Caching)
불변 객체는 변경되지 않으므로 캐싱이 가능하고 동일한 객체를 여러 곳에서 재사용할 수 있어 메모리 사용을 최적화할 수 있습니다.
3. 불변 객체를 구현하는 방법
1. 객체의 상태를 변경하는 메서드를 제공하지 않는다.
2.클래스를 확장할 수 없도록 한다.
public final class ImmutablePerson {
클래스를 final로 선언하면 상속을 막기 때문에 하위 클래스에서 부주의하게 객체의 상태를 변하게 만드는 사태를 막아줍니다.
3.모든 필드를 final, private로 선언한다.
private final String name;
private final int age;
private final List<String> items;
필드가 참조하는 가변 객체를 클라이언트에서 직접 접근해 수정하는 일을 막아줍니다.
4. 참조에 의해 변경가능성이 있는 경우 방어적 복사를 이용해 전달한다.
public List<String> getList() {
return Collections.unmodifiableList(new ArrayList<>(list));
}
방어적 복사란?
방어적 복사(Defensive Copying)는 객체를 외부에 노출할 때 해당 객체의 사본을 만들어 반환하거나, 외부에서 전달받은 객체를 복사하여 내부에 저장함으로써 원본 객체의 변경으로부터 내부 상태를 보호하는 기법
public final class ImmutablePerson {
private final String name;
private final int age;
private final List<String> items;
public ImmutablePerson(String name, int age, List<String> items) {
this.name = name;
this.age = age;
this.items = new ArrayList<>(items);
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public List<String> getList() {
return Collections.unmodifiableList(new ArrayList<>(items));
}
}
4. 정리
- 불변 객체는 자바 프로그래밍에서 안정적이고 예측 가능한 코드를 작성하는 데 중요한 역할을 한다.
- 스레드 안정성, 부작용 최소화, 실패 원자성, 캐싱 등 다양한 장점이 있다.
- 불변 객체의 특성과 구현 방법을 잘 이해해 적절한 상황에 활용하는 것이 중요!
참고
이펙티브 자바
'JAVA' 카테고리의 다른 글
정적 팩토리 메서드란? (0) | 2024.06.10 |
---|---|
[JAVA] 가비지 컬렉션 2편 (알고리즘) (0) | 2024.06.04 |
[JAVA] 가비지 컬렉션이란? (Garbage Collection) 1편 (0) | 2024.06.04 |
[JAVA] Call by Value, Call by Reference (0) | 2024.06.03 |
[JAVA] 래퍼 클래스(Wrapper Class)란? (0) | 2024.05.31 |