JAVA/Effective Java
item 4. 인스턴스화를 막으려면 private 생성자를 사용하라.
Garonguri
2022. 4. 12. 01:23
728x90
- 정적 멤버(정적 메서드, 정적 필드)만 담은 유틸리티 클래스
- 특징
- static 선언을 통해 인스턴스를 생성하지 않고 전역 범위에서 사용할 수 있고, 재사용이 가능하게 한다.
- class field와 method 모두 정적으로 구현되어 있는 경우가 많다.
- 주로 사용하는 경우
- 기본 타입 값이나 배열 관련 메서드를 모아놓을 때 (Java.lang.Math, Java.util.Arrays)
- 특정 인터페이스를 구현하는 객체를 생성해주는 정적 메서드를 모아놓을 때 (Java.util.Collections)
- final Class와 관련된 메서드를 모아놓을 때 (- final class를 상속해서 하위 class 메서드에 넣는것이 불가능함)
- 단점
- 인스턴스로 만들어 쓰기 위해 설계한 클래스가 아님에도 인스턴스를 만들 수 있다.
- static field와 static method만 존재함에도 불구하고 인스턴스를 생성할 수 있게 되어, 사용자에게/협업자에게 혼란을 일으킬 수 있다.
- 인스턴스 생성을 막기 위하여 추상 클래스로 만들더라도 상속해 사용한다면 인스턴스를 만들 수 있다.
- 해결 방안
- 생성자의 접근 제한자를 private로 만든다. 즉, private 생성자를 추가한다.
- 그러나 생성자가 존재함에도 호출할 수 없는 로직이므로, 주석 또는 Exception을 통해 적절한 조치를 취해야 한다
- 특징
- 예시
- Java.lang.Math
public final class Math {
/**
* Don't let anyone instantiate this class.
*/
private Math() {}
public static final double PI = 3.14159265358979323846;
public static int max(int a, int b) {
return (a >= b) ? a : b;
}
//..etc
}
- Java.util.Collections
public class Collections {
// Suppresses default constructor, ensuring non-instantiability.
private Collections() { }
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(List<T> list) {
list.sort(null);
}
// ... etc
}
- private 으로 접근 제한자가 설정되어 있고, static으로 선언되어 있기 때문에 객체를 생성할 수 없지만, 객체 생성 없이도 사용할 수 있다.
- 명시적으로 정의하였지만 직관적이지 않으므로, Assertion Error를 던지면 의미를 효과적으로 전달할 수 있다.
728x90