- 잘 설계된 컴포넌트는 모든 내부 구현을 완벽히 숨겨, 구현과 api를 깔끔히 분리를 한다.
|제어자|같은 클래스|같은 패키지|자손 클래스|전체| |:-:|:-:|:-:|:-:|:-:| |public|O|O|O|O| |protected|O|O|O|X| |default(package-private)|O|O|X|X| |pivate|O|X|X|X|
- 그러면 api가 아닌 내부 구현이 되어 클라이언트 피해없이 언제든 교체, 수정가능
톱레벨(가장 바깥) 클래스나 인터페이스에 부여할 수 있는 접근 수준은 package-private, public 두 가지
- 톱레벨로 두면 같은 패키지 모든 클래스가 접근 가능하지만, 바깥 클래스 하나에서만 접근가능하게 하자.
- public 클래스는 그 패키지의 api인 반면, packate-private 클래스는 내부 구현에 속한다.
- 그 다음 오직 같은 패키지의 다른 클래스가 접근하는 멤버에 한하여 package-private으로 만들자.
- thread safe 하지 않기 때문이다.
- public 가변 필드를 가지게 되면 담을 수 있는 값을 제한할 수 없어 불변식을 보장할 수 없고 필드 수정될때(락획득 같은) 다른 작업을 하지 못해서다.
Serializable을 구현한 클래스는 그 필드들도 의도치 않게 공개 api가 될 수도 있다.
- 가변객체를 참조하면 다른 객체를 참조를 못하지만, 참조된 객체 자체가 수정될 수 있는 문제가 발생한다.
- 클래스에서 public static final 배열 필드를 두거나 이 필드를 반환하는 접근자 메서드를 제공해서는 안된다.
- 길이가 0이 아닌 배열은 모두 변경이 가능하다.
- 해결법 #1
- 배열 private 변경, public 불변 리스트 추가
private static final Thing[] PRIVATE_CALUES = {...};
public static final List<Thing> VALUES = Collections.unmodifialbeList(Arrays.asList(PRIVATE_VALUES));
- 해결법 #2
- 배열 private 변경, 복사본 반환하는 public 메서드 추가 (방어적 복사)
private static final Thing[] PRIVATE_CALUES = {...};
public static final Thing[] values() {
return PRIVATE_VALUES.clone();
}
- 자바 9에서 추가되면서 두가지 암묵적 접근 수준 추가
- 패키지 클래스의 묶음이듯, 모듈은 패키지들의 묶음이다.
- 모듈은 속해있는 패키지 중 공개(export)할 것들을 선언한다.
- public 멤버여도 공개되지 않으면 접근할 수 없다.
- 모듈 시스템을 활용하면 클래스를 외부에 공개하지 않으면서도 같은 모듈을 이루는 패키지 사이에서는 자유롭게 공유할 수 있다.
- 암묵적 접근 수준들은 각각 public, protected 수준과 같으나, 그 효과가 모듈 내부로 한정되는 변종
- 모듈의 jar파일을 자신의 모듈 경로가 아닌 classpath에 두면 그 모듈안의 모든 패키지는 마치 모듈이 없는 것처럼 행동한다.