아이템 13. 클래스와 맴버의 접근 권한은 최소화 하라.
13. 클래스와 맴버의 접근 권한은 최소화 하라.
잘 설계된 모듈과 그렇지 못한 모듈을 구별 짓는 가장 중요한 속성 하나는 모듈 내부의 데이터를 비롯한 구현 세부사항을 다른 모듈에 잘 감추느냐의 여부다.
정보 은닉(information hidding) 또는 캡슐화(encapsulation) : 모듈들 각자 내부적으로 무슨 일을 하는지 신경 쓰지 않도록 구성하는 것
필드나 메서드, 중첩 클래스(nested class), 중첩 인터페이스(nested interface)같은 멤버의 접근 권한은 아래의 네 개 중 하나로 설정할 수 있다.
- private : 선언된 최상위 레벨 클래스 내부에서만 접근 가능
- package-private : 같은 패키지 내의 아무 클래스나 사용 가능, 기본 접근 권한(default access)으로 멤버를 선언 할 때 아무런 접근 권한 수정자(access modifier)도 붙이지 않으면 이 권한으로 설정됨
- protected : 선언된 클래스 및 그 하위 클래스만 사용할 수 있음, 선언된 클래스와 같은 패키지에 있는 클래스에서도 사용 가능
- public : 어디서도 사용 가능
객체 필드(instance field)는 절대로 public으로 선언하지 말자. 변경 가능한 public 필드를 가진 클래스는 다중 스레드 환경에서 안전하지 않다.
배열의 경우, public static final로 선언해도 내부 데이터에 대한 변경이 가능하므로 아래와 같이 사용하자.
private static final Thing[] PRIVATE_VALUES = { ... };
public static final List<Thing> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
혹은
private static final Thing[] PRIVATE_VALUES = { ... };
public static final Thing[] values(){
return PRIVATE_VALUES.clone(); // 개인적으로 clone 하는 것보단 위에 방법이 낳은것 같다.
}
요약해 보면, 접근 권한은 가능하면 최대한 낮추고 최소한의 public API를 설계한 다음 다른 모든 클래스, 인터페이스, 멤버는 API에서 제외하자. 또한 public static final 필드를 제외한 어떤 필드도 public 필드로 선언 하지 말자. 그리고, public static final 필드가 참조하는 객체는 변경 불가능 객채(Immutable Object)로 만들자.