Java

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

yerimkoko 2023. 4. 21. 13:10
728x90

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

정적 메서드만 담은 유틸리티 클래스는 인스턴스로 만들어 쓰려고 설계한 클래스가 아니다.

  • Helper 성격의 factory들.
public class UtilityClass {
    
    public static String hello() {
        return "hello";
    }
    public static void main(String[] args) {
        
        String hello = UtilityClass.hello(); // 이때 인스턴스로 사용되는 것을 추천하지 않는다.
          
    }
}

추상 클래스로 만드는 것으로는 인스턴스화를 막을 수 없다.

  • ⬇️ 아래의 코드처럼 생각할 수 있다.
public abstract class UtilityClass {

    public static String hello() {
        return "hello";
    }
    public static void main(String[] args) {

        UtilityClass utilityClass = new UtilityClass();
        
    }
}
  • 그러나…
public class DefaultUtilityClass extends UtilityClass{

    public static void main(String[] args) {
        DefaultUtilityClass utilityClass = new DefaultUtilityClass(); // 상위 클래스의 생성자를 먼저 만들기 때문에 ... 가능하다.
    }
}
  • UtilityClass를 상속하여 사용이 가능하다. (super class 의 생성자를 호출)
  • 또한 abstract 를 사용하면 이름 때문에 상속을 해서 사용하는 클래스라고 생각할 수 있다.

private 생성자를 추가하면 클래스의 인스턴스화를 막을 수 있다.

  • 그래서 이 방법을 추천한다.
public class UtilityClass {

    **private UtilityClass() {
        throw new AssertionError();
    }**

    public static String hello() {
        return "hello";
    }
}
  • 그럼 왜 못 쓰는 코드를 사용하게 만들까?

그렇기에 생성자에 주석으로 인스턴스화 불가한 이유를 설명하는 것이 좋다.

public class UtilityClass {

    /**
     * 이 클래스는 인스턴스를 만들 수 없습니다.
     */

    private UtilityClass() {
        throw new AssertionError();
    }

    public static String hello() {
        return "hello";
    }
}

상속을 방지할 때도 같은 방법을 사용할 수 있다.