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

제롬·2022년 1월 4일
0

이펙티브자바

목록 보기
4/25

인스턴스화를 하지 않는 유틸리티클래스

정적(static) 메서드와 정적(static) 필드만을 담은 클래스는 객체지향과는 거리가 있지만 쓰임새가 있다.

  • java.lang.Mathjava.util.Arrays 처럼 기본 타입 값이나 배열 관련 메서드들을 모아놓는다.
  • java.util.Collections 처럼 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드(혹은 팩토리)를 모아놓을 수도 있다.
  • final 클래스와 관련한 메서드들을 모아놓을 때도 사용한다.

[정적 메서드와 정적 필드만을 담은 클래스]

public class Decision {
    private static String answer;
    private static String guessAnswer;

    public static boolean isCorrect() {
        return answer.equals(guessAnswer);
    }
}

정적 멤버만 담은 유틸리티 클래스는 인스턴스로 만들어 쓰려고 설계한것이 아니다. 하지만 생성자를 명시하지 않으면 컴파일러가 자동으로 기본생성자(매개변수를 받지 않는 public 생성자)를 만든다.

Decision decision = new Decision();
boolean isCorrect1 = Decision.isCorrect();
    // 잘못된 사용법
boolean isCorrect2 = Decision.isCorrect();
    // 올바른 사용법

인스턴스화를 막는 방법

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

  • 하위 클래스를 만들어 인스턴스화를 생성할 수 있기 때문이다.
  • 하위 클래스를 인스턴스화 하는 것을 본 사용자는 상속해서 쓰라는 뜻으로 오해할 가능성이 있다.
abstract class Decision {
...
}

class SubDecision extends Decision{
... 
}

...
public static void main(String[] args) {
    // abstract 클래스는 인스턴스화 불가능
    // Decision decision = new Decision();

    // 하위 클래스는 인스턴스화 가능
    SubDecision subDecision = new SubDecision();
}

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

public class Decision {
    private Decision() {
        throw new AssertionError(); 
        // 예외를 던진 이유는 클래스 안에서 실수로라도 생성자를 호출하지 않도록 하기 위함이다.
    }
...
public static void main(String[] args) {
    // 'Decision()' has private access in 'Decision'
    Decision decision = new Decision();
}

private 생성자를 사용할 경우

  • 생성자를 private 접근제어자로 추가할 경우 명시적 생성자가 private이기 때문에 클래스 바깥에서는 접근할 수 없다.

  • 이 방식은 상속을 불가능하게 한다.
    (모든 생성자는 상위 클래스의 생성자를 호출하게 되는데, 이를 private으로 선언해 접근할 수 없도록 했기 때문이다.)

  • 생성자가 존재하는데 호출할 수 없기때문에 직관적이지 않다.
    (따라서 적절한 주석을 달아주는 것이 좋다.)

정리

정적 팩터리와 정적 필드만을 담은 유틸리티 클래스를 사용할 경우 인스턴스화를 하려고 설계한것이 아니니 인스턴스화를 막아야한다.

클래스의 인스턴스화를 막는 방법은 추상클래스를 사용하는 방법과 private 생성자를 사용하는 방법이 있다.

추상클래스를 사용하는 방법은 하위클래스를 만들어 인스턴스화를 하는것이 가능해 클래스를 상속해 사용하라는 뜻으로 오해의 소지가 발생할 수 있다.

따라서 인스턴스화와 상속을 모두 불가능하게 하는 private 생성자를 사용하여 인스턴스화를 막겠다는 의지를 확실하게 보여주자.

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

0개의 댓글