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

gang_shik·2022년 2월 18일
0

Effective Java 2장

목록 보기
4/9
post-custom-banner
  • 이따금 단순히 정적 메서드정적 필드만을 담은 클래스를 만들고 싶을 때가 있음

  • 이러한 것들은 인스턴스로 만들어 쓰려고 하는게 아니지만 생성자명시하지 않으면 컴파일러기본 생성자를 만듬(매개변수를 받지 않는 public 생성자가 만들어짐)

  • 이는 추상 클래스로 만드는 것으로는 인스턴스화를 막을 수 없음, 하위 클래스를 만들어 인스턴스화를 하기 때문에, 이를 오히려 상속해서 쓰라고 오해할 수 있음

  • 이런 경우 private 생성자추가하면 클래스의 인스턴스화를 막을 수 있음

public class UtilityClass {
		// 기본 생성자가 만들어지는 것을 막는다(인스턴스화 방지용)
		private UtilityClass() {
			throw new AssertionError();
		}
}
  • 클래스 안에서 실수로라도 생성자를 호출하지 않도록 예외를 던짐

  • 이런 방법은 생성자존재하는데 호출할 수 없으니 직관적인 코드는 아님, 그래서 적절한 주석을 다는게 좋음

  • 이 방식은 상속불가능하게 하는 효과도 있음, 모든 생성자는 명시적이든 묵시적이든 상위 클래스의 생성자호출하게 되는데, 이를 private으로 선언했으니 하위 클래스상위 클래스의 생성자접근할 길이 막힘

해당 아이템에 대한 예시?

인스턴스화를 막아야 하는 경우가 책에서 말한 직접적으로 드는 예시가 무엇인지 좀 더 알아봄

정적 멤버만 담은 유틸리티 클래스인스턴스로 만들어 쓰려고 설계한 것이 아님, 그렇다고 추상 클래스로 만드는 것으로 인스턴스화를 막을 수 없다고 함

이때 private을 통해서 생성자를 만들어서 컴파일러기본 생성자자동으로 만들지도 않음, 그래서 이 private 생성자를 사용하는 것

Math 클래스같은 경우 상속을 위해서도 인스턴스를 위해서도 쓴 것이 아님, 그래서 private생성자를 만든 것

public final class Math {

      private Math() {} 

      public static final double E = 2.7182818284590452354; 
      public static final double PI = 3.14159265358979323846; 

      public static double sin(double a) { 
            return StrictMath.sin(a); // default impl. delegates to StrictMath 
      } 
      public static double cos(double a) { 
            return StrictMath.cos(a); // default impl. delegates to StrictMath 
      } 
      public static double tan(double a) { 
            return StrictMath.tan(a); // default impl. delegates to StrictMath 
      } 
      // 생략 ... 
}
profile
측정할 수 없으면 관리할 수 없고, 관리할 수 없으면 개선시킬 수도 없다
post-custom-banner

0개의 댓글