Item 13. 클래스와 맴버의 접근 권한은 최소화 하라.

잘 설계된 모듈과 그렇지 못한 모듈을 구별 짓는 가장 중요한 속성 하나는 모듈 내부의 데이터를 비롯한 구현 세부사항을 다른 모듈에 잘 감추느냐의 여부다.

정보 은닉(information hidding) 또는 캡슐화(encapsulation) : 모듈들 각자 내부적으로 무슨 일을 하는지 신경 쓰지 않도록 구성하는 것

필드나 함수, 중첩 클래스(nested class), 중첩 인터페이스(nested interface)같은 멤버의 접근 권한은 아래의 네 개 중 하나로 설정할 수 있다.

객체 필드(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)로 만들자.