[Effective Java] 3 - item15 클래스와 멤버의 접근 권한을 최소화하라
item15 클래스와 멤버의 접근 권한을 최소화하라
- 잘 설계된 컴포넌트는 클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 얼마나 잘 숨겼는지에 의해 결정된다.
- 모든 내부구현을 완벽히 숨겨, 구현과 API를 분리한다.
- API를 통해서만 타 컴포넌트와 소통하며 서로의 내부 동작 방식을 알지 못한다.
- -> 정보 은닉 / 캡슐화
정보 은닉의 장점
- 시스템 개발 속도 ↑
- 여러가지 컴포넌트를 병렬로 개발할 수 있다.
- 시스템 관리 비용 ↓
- 컴포넌트를 빨리 파악하여 디버깅 할 수 있고, 다른 컴포넌트로 교체하는 부담도 적다.
- 성능 최적화에 도움
- 다른 컴포넌트에 영향을 주지 않고 타겟이 되는 컴포넌트만 최적화가 가능하다.
- 소프트웨어의 재사용성 ↑
- 기존의 인터페이스를 그대로 사용할 수 있다.
- 큰 시스템을 제작하는 난이도를 낮춰준다.
모든 클래스와 멤버의 접근성을 가능한 한 좁히자. 소프트웨어가 올바로 동작하는 한 가장 낮은 접근 수준을 부여해야 한다.
- Java에서는 이를 위해 다양한 장치를 사용하는데, 접근 제한자가 그 대표적 예시이다.
Java의 접근 제한자
private
: 멤버를 선언한 톱레벨 클래스에서만 접근 가능package-private(=default)
: 멤버가 소속된 패키지 안의 모든 클래스에서 접근 가능하다.protected
:package-private
의 접근 범위를 포함하며, 이 멤버를 선언한 클래스의 하위 클래스에서도 접근 가능하다.public
: 모든 곳에서 접근 가능하다.
톱레벨 수준(파일명 = 클래스명)이 같은 수준에서의 접근제한자는 public
과 package-private
만 사용 할 수 있다.
public
으로 선언하는 경우 공개 API로 사용- 하위호환을 평생 신경써야 한다.
public
클래스의 인스턴스 필드는 되도록public
이 아니어야 한다.(아이템 16)- 필요에 따라
public static final
상수 필드는 공개해도 좋다. (추상 개념 구성요소로서의 상수) public
가변 필드를 가지는 클래스는Thread-safe
하지 않다.
// 해결책 1 : 배열을 private로 만들고, public 불변 리스트를 추가한다.
private static final Thing[] PRIVATE_VALUES = {...};
public static final List<Thing> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
// 해결책 2: 배열을 private로 만들고 이 복사본을 반환하게 한다.
private static final Thing[] PRIVATE_VALUES = {...};
public static final Thing[] values() {
return PRIVATE_VALUES.clone(); // 방어적 복사
}
package-private
로 사용하는 경우 해당 패키지 안에서만 사용 가능- 다음 릴리즈에 내부로직을 변경해도 괜찮다.
public
일 필요가 없는 클래스의 접근 수준을default
클래스로 좁혀야 한다.
private
,package-private
: 해당 클래스의 구현에 해당하므로 공개 API에 영향을 주지 않는다.- 처음에 모든 멤버는
private
으로 -> 필요시package-private
하게 변경
- 처음에 모든 멤버는
- 메서드를 재정의 할 경우에는 접근 수준을 상위 클래스에서보다 좁게 설정 할 수 없다. (리스코프 치환 원칙)
- 인터페이스의 경우 메서드를 모두
public
으로 해야 한다.
- 인터페이스의 경우 메서드를 모두
Java Modules (Java 9~)
- 패키지는 클래스의 묶음인 것 처럼, 모듈(Modules)은 패키지의 묶음이다.
- 모듈은 자신이 속하는 패키지 중 공개(export) 할 것을 선언한다.
- 정의하기 위해 3가지 정보를 작성해야 한다.
- module 명 / 명칭
- 공개할 package (export)
- 공개한 package의
public
접근제한자만 외부에서 접근할 수 있다. - export하지 않았다면,
public
접근제한자가 있어도 접근을 할 수 없다.
- 공개한 package의
- module내 package의 클래스를 사용하기 위해 종속되는 package (require)
- 이 접근 수준은 주의해 사용해야 한다.
- 모듈의 JAR file을 classpath에 두면 모듈 내 모든 패키지가 모듈이 없는 것처럼 행동한다. 즉,
public
클래스 내 모든public
혹은protected
멤버에 접근할 수 있게 하기 때문이다.
Leave a comment