본문 바로가기

Reading Record/이펙티브자바

[아이템 4] 인스턴스화를 막으려거든 private 생성자를 사용하라

개발을 하다보면 "유틸리티 클래스"가 필요한 순간이있다.

유틸리티 클래스는 Common과도 같아서 끝도없이 무거워질 수 있고 객체지향과도 거리가 멀 수 있지만, 분명 쓸모가 있다.

이러한 유틸리티클래스는 대부분 정적 메서드, 정적필드로만 구성되어있다.

 

책에나오는 예시로는

java.util.Arrays, java.langh.Math가 있다

 

Arrays클래스는 배열관련 메서드를 담고있으며,

/*  
 * This class contains various methods for manipulating arrays (such as
 * sorting and searching). This class also contains a static factory
 * that allows arrays to be viewed as lists.
 */

// Suppresses default constructor, ensuring non-instantiability.
private Arrays() {}

 

Math클래스는 상수, 계산과 관련된 메서드를 담고있고 역시나 private 생성자를 가진다

/**
* Don't let anyone instantiate this class.
*/
private Math() {}

 

 

이렇게 기본생성자를 private으로 명시해주는 이유는 자바는 다른 생성자가 없으면 자동으로 기본생성자를 만들어주기 때문이다.

 

즉, 개발자는 의도치않게 인스턴스화를 허용할 수 있다.

 

Q. 그렇다면 추상클래스로 만들면 되지 않을까?

A. 개념적으로 추상클래스는 인스턴스로 만들 수 없다. 하지만 추상클래스를 상속한다면 상황이 달라진다.

인스턴스화를 막기 위해 추상클래스를 만든다면, 클라이언트는 추상클래스를보고 "상속하여 사용하라"는 의미로 받아들일 수 있다. 오히려 더 큰 문제이다.

 

 

그러니 인스턴스화를 막기위해서는 private 생성자를 명시하자. 그리고 주석으로 설명을써주고, 더 신경쓴다면 명시적인 에러를 던져주도록하자.

// 인스턴스화를 막는다.
private NoInstanciate(){
  throw new AssertionError(); // 명시적으로 적어준다
}