JAVA/Effective Java

클래스와 인터페이스 - 규칙 15 변경 가능성을 최소화하라

반응형

immutable 클래스는 그 객체를 수정할 수 없는 클래스이다. 

객체 내부의 정보는 객체가 생성될 때 주어진 것이며, 객체가 살아 있는 동안 그대로 보존된다.

이러한 변경 불가능 클래스를 만드는 이유는 다양하다. 
- 설계가 쉽다.
- 오류 가능성이 적고 안전하다.

생성 규칙
- 객체 상태를 변경하는 메서드를 제공하지 않는다. (setter)
- 상속할 수 없도록 진행한다. 
  => 하위 클래스가 객체 상태가 변경된 것처럼 동작할 수 있다.
  => class에 final을 붙힌다. 
- 모든 필드를 final로 생성한다.
  => 이렇게 생성할 경우 생성된 객체에 대한 참조가 동기화(Synchronization)없이 다른 스레드로 전달
   되어도 안전하다.
- 모든 필드를 private로 선언한다. 
  => 모든 필드를 직접 접근해서 수정하는 경우를 막을 수 있다.
  => public으로 선언하고 final로 지정할 수 있지만 이럴 경우 나중에 클래스의 내부 표현을 변경할 수 
   없게 되기 때문에 좋지 않다.
- 다음과 같은 방식으로 변경 가능 컴포넌트에 대한 독점적 접근법을 보장한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public final class Test {
  private final String alias;
  private final String name;
 
  public Test(String alias, String name) {
    this.alias = alias;
    this.name = name;
  } 
 
  
  //  방어적 복사본을 만들어 기존의 값을 변경하는 것이 아닌 변경된 새로운 값을 만든다.
  public Test addPrifix(String prefix, Test te) {
    return new Test(prefix + te.getAlias(), prefix + te.getName());
  }
 
}
cs



또한 이렇게 방어적 복사본을 계속해서 만들지 않고도 공통으로 사용하는 항목에 대해서 다음과 같이
생성해 두어 공유할 수 있다.


1
2
public static final Test PNP = new Test("pnp" , "inc");
public static final Korea KOR = new Test("kor""public");
cs



이렇게 만들어 놓으면 계속해서 객체를 생성할 이유가 없어서 좋다. 


또한 이런 클래스는 어차피 변경이 되지 않기때문에
clone 메서드나 복사 생성자를 만들 필요도 없고 만들어서도 안된다.

이러한 별경 불가능한 객체의 단점은 위에서 보는거와 같이 새로운 값이 필요할 때마다 객체를 만들어야 한다는 것이다.

그렇지만 이런 문제는 자주 사용하는 연산을 다른 동료 클래스들에서 제공하는 기본연산등을 이용하여 어느정도 완충할 수 있다.

정리하자면.
변경 가능한 클래스로 만들어야할 이유가 없는 클래스의 경우 모드 변경불가능한 클래스로 만들고
만약 그럴 수 엇다면 변경 가능성을 제한하고 특별한 이유가 없는 경우는 모든 필드를 final로 선언한다.

 출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙15 인용.


반응형