[Effective Java] 아이템15 - 클래스와 멤버의 접근 권한을 최소화하라
4장에서는 자바의 심장인 클래스와 인터페이스에 대해 깊게 알아본다.
정보은닉, 캡슐화
클래스 내부 데이터와 내부 구현 정보를 외부 컴포넌트로부터 잘 숨겨야 잘 설계된 컴포넌트로 볼 수 있다.
즉, 내부 구현을 완벽히 숨겨서 오로지 API를 통해서만 다른 컴포넌트와 소통하며 서로의 내부 동작 방식을 신경 쓰지 않아도 되게 만드는 것이다.
접근 제어 메커니즘
private, protected, public 과 같은 접근 제한자로 클래스, 인터페이스, 멤버의 접근성을 명시한다.
모든 클래스와 멤버의 접근성을 가능한 좁혀야 한다.
접근제한자 | 설명 |
---|---|
private | 멤버를 선언한 클래스에서만 접근할 수 있음 |
package-private | 멤버가 소속된 패키디 안의 모든 클래스에서 접근할 수 있음 |
protected | package-private 의 접근 범위를 포함하며, 이 멤버를 선언한 클래스의 하위 클래스에서도 접근할 수 있다. |
public | 모든 곳에서 접근할 수 있다. |
1. 톱레벨 클래스 - public
또는 package-private
결정
외부로 API로서 제공해야 하는 클래스는 public
으로, 외부에서 쓰이지 않고, 해당 package 내부에서만 사용된다면 package-private
으로 선언하자.
package-private
으로 선언하려면 class에 아무런 접근제어자를 명시하지 않으면 된다. (인터페이스의 멤버인 경우 기본적으로 public이 적용된다.)
class Top {
public void print() {
System.out.print("Top!");
}
}
만약, 하나의 클래스에서만 사용하는 클래스가 있다면, 이 클래스를 private static
으로 중첩시켜서 사용하자.
class A {
private static class useThisOnlyInA {
...
}
}
2. public
을 결정했다면 그 외 모든 멤버는 private
으로 만들자.
말 그대로, 클래스의 공개 API를 세심히 설계한 후, 그 외의 모든 멤버는 private
으로 만들자. 그런 다음 오직 같은 패키지의 다른 클래스가 접근해야 하는 멤버에 한하여 package-private
으로 풀어주자
Serializable
을 구현한 클래스에서는 private
또는 package-private
필드들도 의도치 않게 공개 API가 될 수도 있다.
3. 멤버 변수의 접근제어
private
: 가능한 모든 멤버 변수를private
으로 설정하자.protected
: 멤버를protected
로 공개하는 순간, 공개 API로 보고 영원히 해당 권한으로 지원해야 한다.public
:public
클래스의 인스턴스 필드는 되도록 public이 아니어야 한다.- 필드가 가변 객체(ex.. ArrayList)를 참조하거나,
final
이 아닌 인스턴스 필드를public
으로 선언하면 그 필드에 담을 수 있는 값을 제한할 힘을 잃게된다. 왜냐하면 외부에서 해당 값을 수정할 수 있기 때문이다. - 하지만 상수 개념이라면
public static final
필드로 공개해도 좋다. -
private static final COLLECTION_NAME = "item_base";
- 배열은 절대 안된다. 아래와 같은 코드는 외부에서 수정이 가능하다.
-
public static final Thing[] VALUES = { ... };
- 필드가 가변 객체(ex.. ArrayList)를 참조하거나,
배열을 상수로 제공하고 싶을 때
Collections.unmodifiableList
를 사용
private static final String[] PRIVATE_VALUES = {"I", "HAVE", "PEN"};
public static final List<String> VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));
clone
(방어적 복사)로 리턴
public static final String[] values() {
return PRIVATE_VALUES.clone();
}
java9에서 새로 도입된 접근자 - 모듈
패키지가 클래스들의 묶음이듯, 모듈은 패키지들의 묶음이다. 모듈은 자신에 속하는 패키지 중 export할 것들을 선언한다.
JDK 자체가 이 모듈을 활용한 예다. 자바 라이브러리에서 공개하지 않은 패키지들은 해당 모듈 밖에서는 절대로 접근할 수 없다.
댓글남기기