카테고리 없음

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

미미누 2022. 7. 11. 21:52

본 글은 조슈아 블로크의 이펙티브 자바 3판을 읽고 정리한 글입니다.



정적 메서드와 정적 필드만을 담은 클래스를 만드는 경우

1. java.lang.Math와 java.util.Arrays처럼 기본 타입 값이나 배열 관련 메서드를 모아놓는 경우
2. java.util.Collections처럼 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드(혹은 팩터리)를 모아 놓을 수 있음.
3. final 클래스와 관련한 메서드를 모아놓을 때도 사용(final 클래스를 상속해서 하위 클래스에 메서드를 넣는 건 불가능)

정적 멤버만 담은 유틸리티 클래스는 인스턴스로 만들어 쓰려고 설계한 것이 아니지만, 생성자를 명시하지 않을시 컴파일러가 자동으로 기본 생성자를 만듦(매개변수를 받지 않는 public 생성자가 만들어져 공개된 API들에서도 의도치 않게 인스턴스화할 수 있게 된 클래스가 목격될 수 있음)

추상 클래스로 만드는 것으로는 인스턴스화를 막을 수 없음. 왜냐? 하위 클래스를 만들어 인스턴스화 할 수 있기 때문이다. (상속해서 쓰라는 뜻으로도 오해 할 수 있으므로 더 큰 문제이다.)



인스턴스화를 막는 방법은 컴파일러가 기본 생성자를 만들지 못하도록, private 생성자를 추가하여 클래스의 인스턴스화를 막는 것이다.

인스턴스를 만들 수 없는 유틸리티 클래스

public class UtilityClass {
 // 기본 생성자가 만들어지는 것을 막는다(인스턴스화 방지용).
 private UtilityClass() {
   throw new AssertionError();
  }
}

명시적 생성자가 private이니 클래스 바깥에서 접근 할 수 없음 .
클래스 안에서 실수로 생성자를 호출하지 않도록 해준다. 이 방식은 상속을 불가능하게 하는 효과도 있다.
모든 생성자는 명시적이든 묵시적이든 상위 클래스의 생성자를 호출하게 되는데, private으로 선언했으니 하위 클래스가 상위 클래스의 생성자에 접근할 길이 막혀버린다.