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

Jae·2024년 2월 18일

Effective Java

목록 보기
5/11

해당 부분은 책의 순서와 관계없이 이해한 내용을 정리하였다.

인스턴스화를 막기위해 private 생성자를 사용하라는 부분인데, 인스턴스화를 사용하지 않는 경우는 유틸리티 클래스의 경우가 있다. 따라서 static 키워드가 사용되는 경우와 생각되는 문제점과 해결책을 정리하였다.

static 메소드, static 필드 사용 예제

기본 값이나 배열에 관련된 메소드 집합

java.lang.Math/ java.util.Arrays 클래스처럼 산술에 필요한 기본 타입 값이나 배열관련된 사용

public final class Math {

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

  public static final double E = 2.7182818284590452354;

  public static final double PI = 3.14159265358979323846;
}

Math 구현된 부분을 보면 산술시 고정된 값이 필요한 경우 static을 사용한다.

특정 인터페이스를 구현하는 객체들을 포함

public class Collections {
  // Suppresses default constructor, ensuring non-instantiability.
  private Collections() {
  }
  
  private static final int BINARYSEARCH_THRESHOLD   = 5000;
  private static final int REVERSE_THRESHOLD        =   18;
  private static final int SHUFFLE_THRESHOLD        =    5;
  
  @SuppressWarnings("unchecked")
  public static <T extends Comparable<? super T>> void sort(List<T> list) {
    list.sort(null);
  }
  
  public static <T> void sort(List<T> list, Comparator<? super T> c) {
    list.sort(c);
  }
  
  private static <T>
  int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
      // 생략
    return -(low + 1);  // key not found
  }

java.util.Collections 클래스를 보면 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메소드이 모여있는 것을 알 수 있다.

final 클래스로 메소드 집합 만들기

final클래스는 상속이 불가능하기 때문에 메소드를 모아 놓는데 사용될 수 있다.

유틸리티 클래스

  • 위와 같은 인스턴스 메서드와 인스턴스 변수를 제공하지 않고 static 메소드/변수만을 제공하는 클래스들
  • 인스턴스가 무의미하기 때문에 생성하지 못하도록 설계된다.

인스턴스가 무의미하지만, 컴파일러가 자동으로 디폴트생성자를 생성한다. 사용자 입장에서 큰 의미가 없지만 Java Doc에 나타나므로 인스턴스 생성이 가능한 클래스로 생각할 수 있다. 따라서 이를 방지하는 것이 필요하다.

Solution

  1. 추상클래스로 인스턴스화 막기
    -> 추상클래스는 서브클래스를 만들 수 있다. 그렇기에 서브클래스는 인스턴스를 만들 수 있어서 결과적으론 인스턴스를 만들 수 있어서 불가능하며, 인스턴스를 만들지 않기 위해 설계한 건데 상속을 위해 한 것으로 오인하게 할 수도 있다. 불가능
  2. 기본 생성자의 접근제어자를 private로 만들기
    -> 디폴트 생성자가 만들어지지않으며, Java Doc에도 나타나지 않는다. 그치만, 수퍼 클래스의 생성자가 private이기 때문에 서브 클래스가 수퍼클래스를 호출할 수 없으므로 에러가 발생한다.
    위의 앞선 예시들의 java.lang.Math나 java.util.Collections에서 디폴트 생성자를 private를 사용하고 있음도 확인할 수 있다.

참조

Effective Java

0개의 댓글