본문 바로가기

Dev Book Review/Effective Java 3판

[Effective Java] Item4. 인스턴스화를 막으려거든 private 생성자를 사용하라

1. 유틸리티 클래스

- 단순히 정적 메서드와 정적 필드만을 담은 클래스

- 기본 타입 값이나 배열 관련 메서드들을 모아두는 경우 (java.lang.Math, java.util.Arrays)

- 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드(또는 팩터리)를 모아두는 경우 (java.util.Collections)

- final 클래스와 관련한 메서드들을 모아두는 경우

2. 유틸리티 클래스의 인스턴스화를 막는 이유

먼저 이러한 유틸리티 클래스는, 인스턴스로 만들어서 쓰려고 설계한 게 아니다.

하지만 그렇다고 생성자를 작성하지 않으면, 컴파일러가 기본 생성자를 자동으로 만들어준다. 따라서 클라이언트가 이러한 생성자를 통해 유틸리티 클래스의 인스턴스를 만들 수 있다. 이러한 상황을 피하기 위해 직접 유틸리티 클래스의 인스턴스화를 막아준다.

3. 유틸리티 클래스의 인스턴스화를 막는 방법

먼저 해당 클래스를 추상 클래스로 만드는 방법이 존재한다.

하지만 이 방법은, 추상 클래스의 하위 클래스를 만들어 인스턴스화 할 수 있기 때문에 인스턴스화를 완벽하게 막지 못한다.

다만 예제에서 보이다시피 하위 클래스의 인스턴스는 상위 클래스의 필드와 메서드에 접근하지는 못한다.

 

따라서 private 생성자를 추가할 수 있다. 이렇게 하면 기본 생성자가 추가되지 않는다.

또한 클래스 바깥에서는 해당 생성자에 접근할 수 없다. 

 

이때 AssertionError을 반드시 던질 필요는 없지만, 혹시나 클래스 안에서 생성자를 호출하는 경우를 피할 수 있다.

마찬가지로 보다 직관적인 이해를 위해 적절한 주석을 달아주는 게 좋다.

 

추가적으로 하위 클래스가 상위 클래스의 생성자를 호출할 수 없기 때문에, 해당 클래스의 상속을 불가능하게 하는 효과도 있다.