인스턴스화가 필요없는 Utility 클래스 등은 private 생성자를 사용하자
프로젝트를 진행할때 어플리케이션 전역에서 사용하는 기능의 공통 메서드들은 보통 static 멤버로만 이루어진 Utility 클래스로 만들어 사용하곤 합니다. 예를 들자면 문자열을 조작할 때 사용하는 StringUtil 이라거나 DateUtil 등이 있습니다.

예를 들면 org.apache.commons 라이브러리에도 StringUtils가 존재합니다.
public class StringUtils {
 
    public static boolean isEmpty(String str) {
        return str == null || str.length() == 0;
    }
 
    public static boolean contains(String str, String searchStr) {
        if (str == null || searchStr == null) {
            return false;
        }
        return str.indexOf(searchStr) >= 0;
    }
 
 
..생략..
 
}
cs


그런데 이런 static 멤버만 있는 클래스는 굳이 new 키워드를 통해 의미없이 인스턴스화 할 필요가 없습니다. 메모리만 낭비할 뿐이며, 그런 코드를 보는 다른 사용자들 또한 오해하여 인스턴스화 해서 사용할 가능성도 있습니다. 또한 개인적으로 Util 클래스는 인스턴스를 생성하지 않고 사용하는 맛(?)도 하나의 즐거움이라고 생각합니다. 코드상에서도 더욱 깔끔해 보이는 점도 있는데, Util클래스를 사용할때마다 인스턴스화 하는 코드가 필요하다면 가독성에도 좋지 못할것입니다.
String emptyStr = "";
 
 
StringUtils utils = new StringUtils(); //인스턴스화 하여 사용하는 경우
utils.isEmpty(emptyStr);
 
 
StringUtils.isEmpty(emptyStr); //인스턴스화 하지 않고 사용하는 경우
cs





해결법
Java 컴파일러는 우리가 기본생성자를 구현 하지 않는 경우 컴파일 과정에서 자동으로 생성해주는데, Util 클래스를 사용하는 다른 사용자들이 이를 보고 오해하여 사용할 수 있습니다. 따라서 인스턴스화를 막고 싶다면 기본생성자를 명시적으로 선언하는 대신 접근제한자를 private으로 설정 해주면 됩니다.
public class StringUtils {
    
    /**
    *  인스턴스화 하지 않고 사용
    */
    private StringUtils() {
        throw new InstantiationException();
    }
 
cs

 


기본생성자가 private이기 때문에 인스턴스화 할 수 없으며, 상속을 하지 못하게 하는 효과도 있습니다. (하위 클래스에서는 무조건 상위 클래스의 생성자를 호출해야하므로)
여기서 private로 생성자를 만드는것에 그치지 않고 예외까지 던지는 이유는 Util 클래스 내부에서도 생성자를 사용하지 못하도록 한다는 의도를 알리기 위함입니다.

 

블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

,