[Effective Java/아이템17] 변경 가능성을 최소화하라.
# 변경 가능성을 최소화하라.
## 불변 클래스(Immutable Class) ?
- 해당 객체의 내부적인 값들을 변경할 수 없는 클래스를 의미한다. 불변 클래스는 해당 객체가 파괴되는 순간까지 절대 달라지지 않는다.
- 불변 클래스는 가변 클래스보다 설계하고 구현하기 쉽고, side-effect로부터 안전
- 예) String, Wrapper Class, BigInteger, BigDecimal - 설계 구현 사용이 쉽다.
- 오류의 여지가 적고 안전하다.
## 1. 불변 클래스의 5가지 규칙
1) 객체의 상태를 변경하는 메서드(변경자, setter)를 제공하지 않는다.
2) 클래스를 확장할 수 없게 한다. - extend (X)
3) 모든 필드를 final로 선언한다.
4) 모든 필드를 private로 선언한다.
5) 자신 외에는 내부의 가변 컴포넌트에 접근할 수 없도록 한다.
## 2. 불변 객체의 장점
0) 단순
- 불변 객체는 생성된 시점부터 파괴될 때까지 그대로 유지한다.
1) 근본적으로 스레드에 안전
- 여러 스레드가 동시에 사용해도 불변 객체이기 때문에 다른 스레드에 영향을 주지 않아 안전하게 공유하고 사용할 수 있다.
- 동기화할 필요가 없다.
2) 불변 객체는 안심하고 공유가 가능
- 스레드 간 영향을 주고 받을 수 없기 때문
- 방어적 복사도 필요없다> clone 메서드 복사 생성자 필요 없다.
- String 클래스의 복사 생성자는 되도록 사용하지 말자
3) 한번 만든 인스턴스는 최대한 재활용이 가능
- 자주 사용하는 인스턴스를 생성하여, 정적 팩터리를 제공할 수 있다.
4) 불변 객체는 자유롭게 공유할 수 있음은 물론, 불변 객체끼리는 내부 데이터를 공유할 수 있음
5) 객체를 만들 때 다른 불변 객체들을 구성요소로 사용하면 이점이 많다.
- 구조가 복잡해도 불변식 유지가 수월
6) 불변 객체는 그 자체로 실패 원자성을 제공한다.
- 실패 원자성: 메서드에서 예외가 발생한 후에도 그 객체는 메서드 호출 전 상태와 같은 유효한 상태를 가진다.
## 3. 불변 객체의 단점
- 값이 다르면 반드시 독립된 객체로 만들어야 한다. 값의 가짓수가 많으면 이를 모두 만드는데 큰 비용이 필요하다.
1) 흔히 쓰일 다단계 연산들이 예측이 될 때
- 다단계 연산 속도를 높여주는 가변 동반 클래스를 package-privated로 둔다.
- BigInteger는 연산 속도를 높여주는 동반 클래스로 package-privated로 되어있는 MutableBigInteger/SignedMutableBigInteger/BigSieve를 사용할 것으로 예상
2) 예측이 되지 않을 때
- 다단계 연산 속도를 높여주는 가변 동반 클래스를 public으로 둔다.
- 예) StringBuilder/StringBuffer: String 클래스의 연산 속도를 높이기 위함
## 4. 불변 클래스를 만드는 설계 방법
1. final 클래스로 상속을 막는다.
2. 정적 팩터리를 제공하는 방법
- 모든 생성자를 private 혹은 package-private로 만들고 public 정적 팩터리를 제공한다. (캐싱 기능 추가도 가능하다.) public이나 protected 생성자가 없으니 다른 패키지에서는 이 클래스를 확장하는 게 불가능하기 때문이다.
## 정리
- 모든 클래스를 불변으로 만들 수는 없기 때문에 클래스라도 변경 가능한 부분을 최소한으로 줄이는 것이 좋다.
- 클래스가 꼭 필요한 경우가 아니면 불변이어야 한다.
- 다른 합당한 이유가 없다면 모든 필드는 private final이어야 한다.
- 생성자는 불변식 설정이 모두 완료된 초기화가 완벽히 끝난 상태의 객체를 생성해야 한다.
'dev book > Effective Java' 카테고리의 다른 글
[Effective Java/아이템19] 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라. (0) | 2021.11.19 |
---|---|
[Effective Java/아이템18] 상속보다는 컴포지션을 사용하라. (0) | 2021.11.18 |
[Effective Java/아이템16] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라. (2) | 2021.10.24 |
[Effective Java/아이템15] 클래스와 멤버의 접근 권한을 최소화하라. (0) | 2021.10.23 |
[Effective Java/아이템14] Comparable을 구현할지 고려하라. (0) | 2021.10.18 |
댓글 개