불변 클래스의 정의
인스턴스의 내부 값을 수정할 수 없는 클래스로 객체가 파괴되는 순간까지 절대 달라지지 않습니다. 대표적으로 String 클래스가 해당합니다.
불변 클래스의 장점
- 가변 클래스보다 설계, 구현, 사용이 쉽습니다.
- 가변 클래스보다 오류 발생 가능성이 적고 안전합니다.
- 기본적으로 Tread-safe하므로 안심하고 공유할 수 있어서 재사용을 할 수 있습니다.
- 방어적 복사를 할 필요가 없습니다. 따라서 clone메서드나 복사 생성자를 제공하지 않는 것이 좋습니다.
- 불변 객체는 그 자체로 실패 원자성(메서드에서 예외가 발생해도 그 객체는 메서드 호출전과 똑같은 유요한 상태여야 함)을 제공합니다.
불변 객체끼리는 내부 데이터를 공유할 수 있습니다.
public class BigInteger {
final int signum; //부호
final int[] mag; //크기(절대값)
public BigInteger negate() {
//배열(mag)은 가변이지만 복사하지 않고 원본과 공유해도 됩니다.
//원본 인스턴스가 가리키는 내부배열을 그대로 가리킵니다.
return new BigInteger(this.mag, -this.signum);
}
}
불변 클래스의 단점
- 값이 다르면 반드시 독립된 객체로 만들어야 합니다.
불변 클래스 재사용 방법
- 자주 쓰이는 값들을 상수로 제공(public static final)
- 자주 사용되는 인스턴스를 캐싱하여 중복생성을 방지핳는 정적 팩토리를 제공합니다. 이러면 메모리 사용량과 GC비용이 줄어듭니다. 또한, 필요에 따라 클라이언트를 수정하지 않고도 캐시 기능을 덧붙일 수 있습니다.
불변 클래스를 만드는 규칙
- 객체의 상태를 변경하는 메서드(변경자)를 제공하지 않습니다.
- 클래스를 확장할 수 없도록 합니다. 대표적으로 클래스를 final로 선언하거나 private(또는 default)생성자와 public 정적 팩토리 메서드를 제공
- 모든 필드를 final로 선언합니다. 이는 인스턴스를 동기화 없이 다른 스레드로 건네도 문제없이 동작하게끔 보장하는데도 필요합니다.
- 모든 필드를 private로 선언합니다. public final로 선언해도 되지만 나중에 내부 표현을 바꾸지 못하므로 private을 권장합니다.
- 자신 외에는 가변 컴포넌트에 접근할 수 없도록 합니다. 생성자, 접근자 모두 방어적 복사를 합니다.
정리
모든 클래스를 불변 클래스로 만들 수는 없습니다. 그래도 변경 가능한 부분은 최소한으로 줄이는 것이 좋습니다. 그러니 꼭 변경해야하는 필드를 제외하고 모두 private final인 것이 좋습니다.
생성자는 불변식 설정이 모두 완료된, 초기화가 완벽히 끝난 상태의 객체를 생성해야 합니다.
생성자와 정적 팩토리 메서드를 제외한 그 어떤 초기화 메서드도 public으로 제공해서는 안됩니다.
반응형
'스터디 > 이펙티브 자바' 카테고리의 다른 글
[Effective Java] Item19. 상속을 고려해 설계하고 문서화하라 (0) | 2022.05.29 |
---|---|
[Effective Java] Item18. 상속보다는 컴포지션 (0) | 2022.05.29 |
[Effective Java] Item16. public클래스에서는 접근자 메서드 사용 (0) | 2022.05.29 |
[Effective Java] Item15. 클래스와 멤버의 접근 권한을 최소화 (0) | 2022.05.29 |
[Effective Java] Item14. Comparable을 구현할지 고려 (0) | 2022.05.21 |