[Effective Java] Item 4. 인스턴스화를 막으려면 private 생성자를 사용하라
Item 4. 인스턴스화를 막으려거든 private 생성자를 사용하라.
자바를 사용해봤다면 java.utils.Arrays와 java.lang.Math 라이브러리를 본 적이 있으실 겁니다.
두 라이브러리의 공통점이 무엇일까요?
바로 정적 메서드만 제공하는 유틸리티 클래스라는 점입니다.
java.lang.Math 라이브러리 사용 예시
import java.lang.Math;
public static void main(String[] args) {
int answer = Math.abs(5 - 7);
System.out.println(answer);
}
java.util.Arrays 라이브러리 사용 예시
import java.util.Arrays;
public static void main(String[] args) {
int[] arr = {3, 1, 5};
Arrays.sort(arr);
}
유틸리티 클래스
유틸리티 클래스란 새 인스턴스를 만들지 않고 API를 사용하기 위해 오직 정적 멤버만 갖고 있는 클래스를 말합니다.
자바에게는 유틸리티 클래스는 다소 객체 지향적이지 않은 방식의 코드이기도 합니다 😅
그러나 특수 목적을 가지고 있는 비슷한 기능의 메서드나 상수를 모아 캡슐화할 수 있다는 장점이 있습니다.
유틸리티 클래스는 어떻게 새 인스턴스를 생성하지 않을 수 있나요?
모든 클래스는 기본 생성자가 필요할텐데,
누군가 실수로 기본 생성자를 통해 유틸리티 클래스를 인스턴스화하지는 않을까요?
인스턴스화를 막고 싶다면..
인스턴스화를 막는 방법은 바로 생성자를 private 으로 설정하는 것입니다.
클래스 바깥에서는 절대 private 생성자에 접근할 수 없게 됩니다.
혹시 클래스 안에서 실수로 생성자를 호출할 수 있으니, 생성자를 호출했다면 AssertionError를 던지도록 합니다.
public class UtilityClass {
// 인스턴스화 방지용
private UtilityClass {
throw new AssertionError();
}
...
}
존재하는 생성자를 호출하지 못하게 private으로 설정하는 코드는 다른 사람들이 이해하기 어렵습니다.
적절한 주석을 달아 인스턴스화를 방지한다는 사실을 알려주세요.
private 생성자를 사용할 때의 장점은 다음과 같습니다.
1. 인스턴스화를 방지한다.
2. 상속을 불가능하게 한다.
모든 하위 클래스의 생성자는 상위 클래스의 생성자를 호출해야 합니다.
그러나 생성자를 private으로 선언하면 하위 클래스가 상위 클래스의 생성자에 접근하지 못합니다.
public class ChildUtilityClass extends UilityClass {
public ChildUtilityClass() {
//상위 클래스의 생성자에 접근하지 X
//super();
}
}