시스템 개발 속도를 높인다.
- 여러 컴포넌트를 병렬로 개발할 수 있기 때문.
시스템 관리 비용을 낮춘다.
- 각 컴포넌트를 더 빨리 파악하여 디버깅 가능
- 다른 컴포넌트로 교체하는 부담을 줄여줌
정보 은닉 자체가 성능을 높여주지는 않지만 성능 최적화에 도움을 준다.
- 완성된 시스템을 프로파일링해 최적화할 컴포넌트를 정한 다음 다른 컴포넌트에 영향을 주지 않고 해당 컴포넌트만 최적화할 수 있기 때문이다.
소프트웨어 재사용성을 높인다.
- 외부에 거의 의존하지 않고 독자적으로 동작할 수 있는 컴포넌트라면 그 컴포넌트와 함께 개발되지 않은 낮선 환경에서도 유용하게 쓰일 가능성이 크기 때문.
큰 시스템을 제작하는 난이도를 낮춘다.
- 시스템 전체가 완성되기 전에도 개별 컴포넌트의 동작을 검증할 수 있기 때문이다.
모든 클래스와 멤버의 접근성을 가능한 좁혀야 한다.
톱레벨 클래스와 인터페이스에게 부여할 수 있는 접근 수준은 package-private과 public 두가지이다.
패키지 외부에서 사용할 이유가 없다면 package private으로 선언하여 사용한다.
public class Name {
private String privateName = "현태";
String packagePrivateName = "ヒョンテ";
protected String protectedName = "炫炱";
public String publicName = "Hyuntae";
}
접근 수준을 상위 클래스보다 좁게 설정할 수 없다
- 상위 클래스의 인스턴스는 하위 클래스의 인스턴스로 대체해 사용할 수 있어야 한다는 리스코프 치환 원칙에 위배되고, compile오류가 발생한다.
public 클래스의 인스턴스필드는 되도록 public이 아니어야 한다.
길이가 0이 아닌 배열은 모두 변경이 가능하다.
public static final String[] VALUE = { ... };
위 코드는 아래와 같이 수정이 가능하다.
AccessModifierTest test = new AccessModifierTest();
test.VALUE[0] = "나는 해커다";
String[] testValue1 = test.VALUE;
for (String s : testValue1) {
System.out.println("s = " + s);
} // {"나는 해커다", ...}
위와 같이 보안에 허점이 존재하고, 불변성을 지킬수 없기에 아래와 같은 두가지 방법으로 해결할 수 있다.
private static final String[] PRIVATE_VALUES = {...};
public final List<String> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
private static final String[] PRIVATE_VALUES = {...};
public static final String values() {
return PRIVATE_VALUES.clone();
}
1번은 public 배열을 private 으로 만들고 public 불변 리스트를 추가하는 방법이고,
2번은 배열을 private으로 만들고 그 복사본을 반환하는 방어적 복사의 방법이다.
꼭 필요한 것만 골라 최소한의 public API를 설계하자.
그 외에는 클래스, 인터페이스, 멤버가 공개되지 않도록 해야 한다.
public 클래스는 상수용 public static final 필드 외에는 어떠한 public 필드도 가져서는 안되며 참조하는 객체가 불변인지 확인하라.