본문 바로가기

Reading/Effective Java

[Effective-Java] Item 4. 인스턴스화를 막으려거든 private 생성자를 사용하라

정적 메소드와 정적 피드만을 담은 클래스를 만들고 싶을 때가 있다.

 

  1. java.lang.Math와 java.util.Arrays처럼 기본 타입 값이나 배열 관련 메소드들을 모아놓기 위해
  2. java.util.Collections처럼 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드를 모아놓기 위해
  3. final 클래스를 상속하여 하위 클래스에 메소드를 넣는 것은 불가능하니 final관련 클래스와 관련한 메소드들을 모아놓기 위해

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

추상클래스로 만드는 것은 하위 클래스를 만들어 인스턴스화 하면 되기 때문에, 막을 수 없다.

그리고 생성자를 명시하지 않으면 컴파일러가 자동으로 기본생성자를 만들기 때문에 private 생성자를 추가해 인스턴스화를 막아야한다.

 

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

 

꼭 예외를 던질 필요는 없지만 클래스 안에서 실수로라도 생성자를 호출하는 것을 막기 위함이다.

그리고 생성자가 있음에도 호출할 수 없으니 적절한 주석이 필요하다.

 

모든 생성자는 명시적이든 묵시적이든 상위 클래스의 생성자를 호출하게 되고, 이를 private으로 선언했으니

하위클래스가 상위클래스의 생성자에 접근할 길이 막혀 상속을 불가능하게 하는 효과도있다.

 

springframework.util


위와는 예외적이지만, springframework.util의 StringUtils는 추상 클래스로 구현을 했다.

이 추상클래스를 만약 상속해서 쓴다고 하더라도, static 필드와 메소드만 있으니 생성자가 가능하다고 해도 사용할 게 없다.

Spring에서 utils는 대체로 abstract로 만드는 경향이 있어보였다.

 

 

 

* 위 글은 EffectiveJava 3/E 책 내용을 정리한 글로, 저작권 관련 문제가 있다면 댓글로 남겨주시면 즉각 삭제조치 하겠습니다.