ITEM 17
변경 가능성을 최소화하라
서론
불변 클래스는 가변 클래스보다 설계, 구현하기가 쉽다. 또한 오류가 생길 여지도 적고 훨씬 안전하다.
클래스를 불변으로 만드는 5가지 규칙
-
객체 상태를 변경하는 메서드(변경자)를 제공하지 않는다.( ex: setter 메서드 )
-
클래스를 확장할 수 없도록 한다.
-
모든 필드를 final로 선언한다.
-
모든 필드를 private 으로 선언한다.
-
자신 외에는 내부 가변 컴포넌트에 접근할 수 없도록 한다.
-> 만약 접근자 메서드를 통해 내부 가변 값을 반환해야 한다면 방어적 복사를 수행하자.
불변 객체의 장점
-
불변 객체는 근본적으로 스레드 안전하여 따로 동기화할 필요 없다.
-> 객체의 변동이 없으니 여러 스레드에서 접근해도 절대 훼손되지 않는다.
-
한번 만든 인스턴스는 최대한 재활용 하자.
-> 정적 팩터리 (아이템 1)를 제공할 수 있다. (Ex: Biginteger.class)
-
방어적 복사가 필요 없다
-> 불변 객체를 복사해도 항상 원본이랑 같기 때문에 굳이 clone 메서드나 복사 생성자를 제공하지 말자.(불필요한 객체 생성 방지)
- 불변 객체는 자유롭게 공유할 수 있음은 물론, 불변 객체끼리는 내부 데이터를 공유할 수 있다.
-
객체를 만들 때 다른 불변 객체들을 구성요소로 사용하면 이점이 많다.
-> 유일 값이기 때문에 예를 들어 (Set)의 원소로 쓰기 안성맞춤이다. 즉 불변식을 유지할 수 있다.
-
불변 객체는 그 자체로 실패 원자성을 제공한다.(아이템 76)
-> 상태가 절대 변하지 않으니 잠깐이라도 불일치 상태에 빠질 가능성이 없다.
불변 객체의 단점
-
값이 다르면 반드시 독립된 객체로 만들어야 한다.
-> 값의 가짓수가 많다면 이들을 많이 만드는데 많은 비용이 든다.
예를 들면
public static void main(String[] args) {
String count = "";
for (int i = 0; i <10; i++) {
count +=String.valueOf(i);
System.out.println(count);
}
}
다음과 같은 경우 String의 인스턴스를 계속해서 만든다.
따라서 다음과 같은 경우 StringBuilder 가변 동반 클래스를 제공하자.
불변 클래스를 만드는 설계 방법
-
final 클래스로 선언 -> 상속을 못하게 한다.
해당 방법보다 모든 생성자를 private 혹은 package-private으로 만들고 정적 팩토리(아이템 1)를 제공하자
이 방법이 조금 더 유연한 방법이다.
결론
-
getter 메서드가 있다고 해서 무조건 setter를 만들지는 말자.
-> 클래스는 꼭 필요한 경우가 아니라면 불변이어야 한다.
-
불변으로 만들 수 없는 클래스라도 변경할 수 있는 부분을 최소한으로 줄이자.
-> 꼭 변경해야 할 필드를 뺀 나머지는 final로 선언하자.
-> 아이템 15의 조언과 종합하자면 다른 합당한 이유가 없다면 모든 필드는 private final 이어야 한다.
-
생성자는 불변식 설정이 모두 완료된 , 초기화가 완벽히 끝난 상태의 객체를 생성해야 한다.
->확실한 이유가 없다면 생성자와 정적 팩토리 외에는 그 어떤 초기화 메서드도 public dmfh wp
'Book Review > effective-java' 카테고리의 다른 글
[ITEM20] 추상 클래스보다는 인터페이스를 우선하라. (0) | 2021.02.16 |
---|---|
[ITEM18] 상속보다는 컴포지션을 사용하라 (0) | 2021.02.14 |
[ITEM16] public 클래스에서는 public 필드가 아닌 접근자 메서드를 사용하라 (0) | 2021.02.12 |
[ITEM15] 클래스와 맴버의 접근 권한을 최소화하라 (0) | 2021.02.10 |
[ITEM14] Comparable 을 구현할지 고려하라 (0) | 2021.02.09 |