잘 설계된 컴포넌트
- 외부 컴포넌트로부터 얼마나 잘 숨겼느냐, 오직 내부 내용을 완벽히 숨겨, API를 통해서만 외부와 소통하는 것을 정보 은닉, 혹은 캡슐화 라고 한다.
- 정보 은닉은 시스템 개발 속도를 높이거나 관리 비용을 낮추고 재사용성을 높이는 등의 장점을 보인다.
자바에서는 정보 은닉을 위한 다양한 장치를 제공하는데 그중 하나가 바로
접근 제어 매커니즘
- 접근 제한자(private, protected, public)로 클래스, 인터페이스, 멤버의 접근성을 명시한다.
- 기본 원칙 : 모든 클래스와 멤버의 접근성을 가능한 한 좁히기
- SW가 올바로 동작하는 수준에서 가장 낮은 접근 수준을 부여
- 접근 수준(낮은 것부터)
- private : 멤버를 선언한 톱레벨 클래스에서만
- package-private : 멤버가 소속된 패키지 안의 모든 클래스에서 접근 가능, 접근 제한자 명시 X 적용되는 패키지 접근 수준
- protected : package-private 의 접근 범위를 포함, 이 멤버를 선언한 클래스의 하위 클래스에서 접근 가능
- public : 모든 곳
적용
- 클래스의 공개 API를 세심히 설계 후, 그 외 모든 멤버는 private으로
- 같은 패키지의 다른 클래스가 접근해야 한다면 (private ->)package-private
- private & package-private 모두 외부에는 영향 X
- package-private -> protected : 접근 대상 범위가 엄청나게 넓어짐(주의) => 공개 API이므로 영원히 지원돼야 함😩
- protected 멤버 수가 적은 것이 좋음
- 상위 클래스 메서드 재정의시 : 상위 클래스보다 좁게 설정 할 수가 없다 (리스코프 치환 원칙, item-10)
- public 클래스의 인스턴스 필드는 publicX(item-16)
- public 가변 필드를 갖는 클래스는 일반적으로 스레드 안전 X
- 해당 클래스가 표현하는 추상 개념을 완성하는데 꼭 필요한 구성요소로써의 상수라면 public static final 필드로 공개해도 됨
- 클래스에서 public static final 배열 필드를 두거나 이 필드를 반환하는 접근자 메서드를 제공하면 X
- 배열은 변경 가능한 값
public static final Thing[] VALUES = { ... };
- 해결책(아래)
public static final 배열 해결책
- public 배열을 private으로, public 불변 리스트 추가
private static final Thing[] PRIVATE_VALUES = { ... };
public static final List<Thing> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
- private 배열, public 복사본 메서드 추가 -> 방어적 복사(item-50)
private static final Thing[] PRIVATE_VALUES = { ... };
public static final Thing[] values() {
return PRIVATE_VALUES.clone();
}
상황에 따라서 둘 중 하나 선택 가능
모듈시스템

- 모듈은 패키지들의 묶음
- 자바9부터 모듈 내부에서 속하는 패키지 중 공개(export)할 것들을 정의 가능 -> 그 외에 것들은 외부에 영향X
핵심 정리
프로그램 요소의 접근성은 가능한 한 최소한으로 하라. 꼭 필요한 것만 골라 최소한의 public API를 설계하자. 그 외에는 클래스, 인터페이스, 멤버가 의도치 않게 API로 공개되는 일이 없도록 해야 한다. public 클래스는 상수용 public static final 필드 외에는 어떠한 public 필드도 가져서는 안 된다. pubilc static final 필드가 참조하는 객체가 불변인지 확인하라.