불변 클래스는 변경 가능성을 최소화하기 위해 설계된 클래스이며, 한 번 생성되면 내부 상태를 변경할 수 없다.
불변 클래스 구현 규칙
객체의 상태를 변경하는 메서드를 지원하지 않는다
클래스를 확장할 수 없도록한다.
클래스를 final 로 설정한다
생성자를 private 으로 설정하고 정적 팩터리 메서드를 제공한다 (유연성 높음, 캐싱을 통한 성능 향상)
모든 필드를 final 로 선언한다. (성능을 위해 외부에 보여질 필드만 final 로 선언하도록 완화할 수 있다.)
모든 필드를 private로 선언한다. (public final 로도 불변 클래스는 만들 수 있으나, 표현 방식을 변경할 수 없기에 권장되지 않는다.)
자신 외에는 내부의 가변 컴포넌트에 접근할 수 없도록 한다. (방어적 복사를 수행하여 직접 가변 컴포넌트에 접근하지 못하게 한다.)
불변 클래스의 장점
근본적으로 스레드 안전하다.
여러 클래스가 자주 접근하는 필드는 상수로 처리하고 정적 팩터리를 통해 제공하여 캐싱을 통해 메모리 사용량과 가비지 컬렉션 비용을 줄일 수 있다.
자유롭게 공유할 수 있으므로 방어적 복사도 필요 없다.
다른 불변 객체와 내부 데이터를 공유할 수 있다.
객체의 구성요소로 사용하면 불변식을 유지하기 수월하다.
그 자체로 실패 원자성
을 제공한다.
불변 클래스 단점
값이 다르면 반드시 독립된 객체로 따로 만들어야한다.
경우의 수가 많다면 불필요하게 많은 클래스를 생성해야할 수 있다.
중간 단계를 거치면서 객체들을 생성한다면 그 객체들 역시 버려지면서 성능에 좋지 않다.
단점 보완 방법
자주 쓰이는 여러 단계의 걸친 연산이 필요할 경우 미리 기본 기능으로 제공한다.
가변 동반 클래스
를 통해 복잡한 연산을 미리 처리하여 제공한다.
추가.
불변 클래스로 활용할 수 없는 객체일지라도 변경할 수 있는 부분을 최소화하자.
생성자는 초기화가 완벽히 끝난 상태의 객체를 생성하도록 하자.
참고.
실패 원자성: 메서드에서 예외가 발생한 후에도 그 객체는 여전히 유효한 상태를 유지하는 것
가변 동반 클래스: 불변 클래스를 기반으로 하여 불변 객체와 함께 사용되는 클래스로, 추가적인 기능이나 연산을 제공