
item4 에서는 정적 메서드와 정적 필드만을 담은 클래스를 왜 이런 클래스가 객체 지향적이지 않다는 것인지 어떻게 안전하게 만드는지를 말한다.
java.lang.MathMath.abs(), Math.max(), Math.random() 같은 수학 연산 메서드를 static으로 제공한다.java.util.ArraysArrays.sort(), Arrays.copyOf(), Arrays.toString() 등을 static 메서드로 제공한다.java.util.CollectionsCollections.unmodifiableList(), Collections.singletonList() 등은 내부적으로 인터페이스를 구현한 객체를 생성해서 반환하기도 한다.순수한 기능만 모아서 제공해야 할 때는 정적 유틸리티 클래스를 사용한다.
유틸리티 클래스는 인스턴스를 만들어 쓰려고 설계한 것이 아니다. 그냥 두게되면 누군가가 실수로 인스턴스를 만들거나 오해해서 상속해서 쓰려고 할 수 있다. 그렇기 때문에 인스턴스 화를 막아줘야한다.
자바는 클래스에 생성자를 전혀 작성하지 않으면, 기본 생성자(public)를 자동으로 만들어 준다.
public class UtilityClass {
// 여기에 아무 생성자도 없으면...
// 컴파일러가 자동으로 public UtilityClass() {} 를 만들어낸다.
}
이렇게 되면 생성자를 통한 인스턴스화가 가능해져 버린다.
private 생성자를 추가한다.public class UtilityClass {
// 기본 생성자가 만들어지는 것을 막는다(인스턴스화 방지)
private UtilityClass() {
throw new AssertionError("No UtilityClass instances for you!");
}
public static String doSomething(...) {
// ...
}
// 그 외 정적 메서드 및 필드...
}
throw new AssertionError() 같은 예외를 던질 수도 있다.private을 사용하면 상속도 불가능하게 된다. 하위 클래스의 생성자는 반드시 상위 클래스 생성자를 호출해야 하는데, 상위 클래스의 기본 생성자가 private이므로 상속이 불가능하게 된다.private 생성자를 명시해야 한다.throw new AssertionError() 예외를 던져서 실수로라도 생성자를 호출하는 일을 방지하고, 주석을 통해서 인스턴스화 불가 의도를 전달한다.