불변 객체를 사용해야하는 이유와 불변 객체 생성 방법

Red Culture·2021년 7월 23일
0

불변 객체란

객체 생성 이후 객체 내부의 상태가 변하지 않는 것을 의미한다. 객체 내부의 상태를 제공하는 메서드를 제공하지 않거나 제공하는 경우 방어적 복사를 통해 제공한다.

얕은 복사와 깊은 복사 그리고 방어적 복사

  • 얕은 복사
    객체를 복사할 때 해당 객체만 복사하여 새로운 객체를 생성한다. 복사한 객체의 인스턴스 변수는 원본 객체의 인스턴스 변수와 같은 메모리 주소를 참조한다. 그렇기 때문에 복사한 객체의 값이 바뀌면 원본 객체의 값도 같이 바뀌게 된다.

  • 깊은 복사
    객체를 복사할 때 해당 객체와 인스턴스 변수까지 모두 복사하는 방식으로 모두 복사해서 새로운 주소에 담기 때문에 원본 메모리 주소를 참조하지 않는다.
    1) 복사 생성자나 복사 팩토리를 사용해서 복사하기
    2) 직접 객체를 생성해서 복사하기
    3) Cloneable을 구현하여 clone() 재정의하기
    -> clone() 재정의는 final 인스턴스 또는 배열이 아닌 경우 사용을 권장하지 않는다.
    (가변 상태인 객체를 복사하면 clone된 객체의 요소가 null이 될 수 있다.)

  • 방어적 복사
    생성자의 인자로 받은 객체의 복사본을 만들어 내부 필드를 초기화하거나 getter 메서드에서 내부의 객체를 반환할 때 객체의 복사본을 만들어 반환한다. 외부에서 객체를 변경해도 내부의 객체는 변경되지 않는다.

public class User {
    private final UserInfo age;

    public User(UserInfo age) {
        this.age = age;
    }

    public UserInfo getAge() { return age; }
}

// 생성자에 방어적 복사 적용
public User(UserInfo age) {
    this.age = new UserInfo(age.getAge());
}

// getter 메서드에 방어적 복사 적용
public UserInfo getAge() {
    return new UserInfo(age.getAge());
}

불변 객체(Immutable Object)를 사용해야 하는 이유

1) Thread-Safe하여 병렬 프로그래밍에 유용하고, 동기화를 고려하지 않아도 된다.
공유 자원이 불변이기 때문에 항상 동일한 값을 반환하기 때문이다.

2) 실패 원자적인 메서드를 만들 수 있다.
어떠한 예외가 발생되더라도 메서드 호출 전의 상태를 유지할 수 있어서 예외 발생 전과 똑같은 상태로 다음 로직을 처리할 수 있다.

3) 캐시나 Map, Set 요소로 활용하기 좋다.
캐시나 Map, Set으로 객체가 변경될 때 별도로 갱신 작업을 해주지 않아도 된다.

4) 부수효과를 피해 오류를 최소화 할 수 있다.
*부수효과: 변수의 값이 바뀌거나 객체의 필드값을 설정하거나 예외나 오류가 발생하여 실행이 중단되는 현상

5) 메서드 호출 시 파라미터 값이 변하지 않는 다는 것을 보장할 수 있다.

6) 가비지 컬렉션 성능을 높일 수 있다.
가비지 컬렉터가 스캔하는 객체의 수가 줄기 때문에 스캔해야 하는 메모리 영역과 스캔에 필요한 시간이 줄어들 것이고, GC 수행 시 지연시간도 줄어들 것이다.

불변 객체 생성 방법

1) 클래스를 final로 선언하기
2) 모든 클래스 변수를 final, private으로 선언하기
3) 객체를 생성하기 위한 생성자나 정적 팩토리 메서드를 추가하기
*정적 팩토리 메서드: 직접적으로 생성자를 통해 객체를 생성하는 것이 아닌 메서드를 통해서 객체를 생성하는 것
4) 참조에 의해 변경 가능성이 있는 경우 방어적 복사를 통해 전달하기

*참고 자료
https://mangkyu.tistory.com/131
https://velog.io/@miot2j/%EC%96%95%EC%9D%80%EB%B3%B5%EC%82%AC-%EA%B9%8A%EC%9D%80%EB%B3%B5%EC%82%AC-%EB%B0%A9%EC%96%B4%EC%A0%81-%EB%B3%B5%EC%82%AC%EB%9E%80
https://jackjeong.tistory.com/100

profile
자기 개발, 학습 정리를 위한 블로그

0개의 댓글