ABOUT ME

beck33333@naver.com

Today
Yesterday
Total
  • private 생성자로 noninstantiability를 강제할 것
    JAVA/Effective java 2020. 12. 30. 15:08
    • 단순히 static 메서드와 static 필드를 모아두는 유틸리티 클래스들을 만들고 싶을 때가 있다.
    • OOP적 사고와는 다소 거리가 있지만 나름의 쓰임새는 있다.
    • Arrays에 배열 관련 메서드, Collections에 정적 메서드 와 팩토리 등이 그 예이다.
    • 또한 final 클래스와 관련된 메서드들을 모아놓을 때도 사용하게 된다. final 클래스를 상속해서 하위 클래스에 메서드를 넣는 것은 불가능하기 때문이다.

     

     

    • 따라서 이같은 유틸리티 클래스는 인스턴스를 만들어 쓰려고 설계한 게 아니다.
    • 하지만 생성자를 명시하지 않으면 생성되는 기본 생성자는 public한 생성자이다. 
    • 클라이언트는 이 생성자가 자동 생성된 것인지 구분할 수 없다.
    • 실제로 공개된 API들도 의도치 않게 인스턴스화할 수 있게 된 클래스가 있다.

    상속받은 자식 클래스

    • 이를 막기 위해 추상 클래스를 사용하는 경우도 있지만 인스턴스화를 막을 수는 없다.
    • 상속받아서 하위 클래스를 인스턴스로 만들 수 있기 때문이다.
    • 이를 본 사용자는 상속해서 쓰라는 뜻으로 오해할 수 있으니 더 큰 문제가 될 수도 있다.

     

    • 따라서 명시적으로 private 생성자를 추가해야 한다. 그러면 클래스의 인스턴스화를 막을 수 있다.

     

     

     

    • AssetionError는 꼭 필요하진 않지만, 그렇게 하면 의도치 않게 생성자를 호출한 경우에 에러를 발생시킬 수 있고, private 생성 자기 때문에 상속도 막을 수 있다.
    • 생성자를 제공하지만 쓸 수 없기 때문에 직관에 어긋나는 점이 있는데,
    • 그 때문에 위에 코드처럼 주석을 추가하는 것이 좋다.
    • 부가적으로 상속도 막을 수 있다.
    • 상속한 경우에 명시적이든 암묵적이든 상위 클래스의 생성자를 호출해야 하는데,
    • 이 클래스의 생성자가 private이라 호출이 막혔기 떄문에 상속을 할 수 없다.

     

     

    스프링의 String 관련 Util 클래스 살펴보기


     

    • 이 클래스도 Util 클래스들 중 하나이다.
    • abstract으로 만들어 놓은 것을 확인할 수 있지만 private으로 생성자를 만들지는 않고 있다.

     

     

     

    • 왜 책에서 나온 예처럼 private 생성자를 굳이 만들지 않은 걸까??
    • 앞선 예를 가지고 하위 클래스를 통해 getName에 접근해보자.

     

    • getName()이 만들어지긴 하지만 ignored 된다고 UtilityClass.getName()으로 고쳐달라는 것을 확인할 수 있다.
    • 하지만 이런 자식클래스를 만들어서 번거롭게 인스턴스를 만들 일은 없다고 생각한 게 아닐까 싶다.

     

    참고 자료 


    이펙티브 자바

Designed by Tistory.