(Effective Java 2/E) 104. Item 4 - Enforce noninstantiability with a private constructor

Enforce noninstantiability with a private constructor

  • 2판 제목 : 객체 생성을 막을 때는 private 생성자를 이용하라
  • 3판 제목 : 인스턴스화를 막으려거든 private 생성자를 사용하라.

정적 메서드나 정적 필드만이 모인 클래스는 객체 지향적 측면에서 잘못된 것일까?

이러한 클래스도 꼭 필요한 경우가 있다.

대표적인 예시로 java.lang.Mathjava.util.Arrays 클래스를 들 수 있다.

특정 인터페이스를 구현하는 객체를 만드는 팩토리 메서드를 모아두는 java.util.Collections도 있다.

또한 클래스를 상속받지 못할 목적으로 일부러 final로 선언하는 유틸리티 계열 클랫드르도 존재한다.

예시로 들은 클래스를 오히려 객체를 만들 수 있다면 이상할 것이다.

어떻게 객체 생성을 못하도록 할 수 있을까?

의도적으로 생성자를 제거하더라도 컴파일러는 묵시적으로 기본 생성자를 만들어낸다.

abstract 키워드로 선언하여도 상속으로 우회해서 객체를 생성할 수 있다.

가장 간단하고 확실한 방법은 명시적 생성자를 작성하되, private 으로 선언해버리는 것이다.

아래는 그 예시이다.

1
2
3
4
5
6
7
public class Utility {
// ...
private Utility() {
throw new AssertionError();
}
// ...
}

리플렉션에 대한 방어를 위해 AssertionError를 추가하는 등의 조치를 취했으므로,

이제 Utility 클래스는 어떤 상황에서도 객체를 생성할 수 없다.

용도에 따라 이러한 클래스 디자인도 있음을 인지하자.