변경 가능성을 최소화하자

불변 클래스란 간단히 말해 그 인스턴스의 내부 값을 수정할 수 없는 클래스다.

  • 객체의 상태를 변경하는 메소드를 제공하지 않는다.
  • 클래스를 확장할 수 없도록 한다. (클래스에 final 선언 혹은 public 생성자에 exception 던지도록)
  • 모든 필드를 final로 선언
  • 모든 필드를 private로 선언
  • 자신 외에는 내부 가변 컴포넌트에 접근할 수 없도록 한다.

불변 객체는 근본적으로 ThreadSafe 처리할 필요는 없다. 또한 불변 클래스는 인스턴스 캐싱을 해서 같은 인스턴스를 중복 생성하지 않게 해주는 정적 팩토리를 제공할 수 있다. 이렇게 하면 메모리 사용량과 GC 비용이 줄어든다. 불변 객체는 자유롭게 공유할 수 있음은 물론, 불변 객체끼리는 내부 데이터를 공유할 수 있다. 예를 들어 BigInteger의 negate 메소드는 크기가 같고 부호만 반대라면 새로운 BingInteger를 생성하는데 원본 인스턴스를 공유한 다른 인스턴스를 (리소스를 최소한으로 하는 방향으로) 만들 수 있다. 또한 불변 객체는 그 자체로 실패 원자성을 제공한다. (불변이기에 실패해도 내부 값은 유효하다.)

단점 역시 존재한다. 값이 다르면 반드시 다른 독립된 객체로 만들어야 한다. 이를 해소하는 방법은 미리 연산을 예측해서 기본 기능을 만들거나 예측할 수 없다면 가변 동반 클래스로 제공하는 것이다. 예를 들어 StringBuilder가 있다.

  • 여튼 정리하면 public class - private field를 기본으로 하자.
  • 가능하면 불변 클래스를 만들기 위해서 필드에 final을 붙이자. 그게 아니더라도 최대한 붙이자
  • 그리고 getter/ setter를 쓰자! 무조건은 아니다.
  • 생성자는 불변성을 띨 수 있는 초기화가 모두 완료된 완벽한 상태의 객체를 생성해야 한다.