JAVA/Effective Java

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

꾸준함. 2024. 1. 20. 07:06

객체지향임에도 불구하고 간혹 인스턴스를 생성하지 말라고 권장하는 케이스가 있습니다.

보통 static 한 메서드들만 가지고 있는 유틸성 클래스가 위 케이스에 해당합니다.

 

인스턴스화를 막는 방법은 아래와 같이 두 가지가 있습니다.

  • private 생성자를 통해 인스턴스화 방지
  • abstract 클래스로 생성하여 인스턴스화 방지
    • 이 방법은 상속을 통해 우회적으로 생성자를 호출할 수 있으므로 불완전한 방법

 

방법 1. private 생성자를 통해 인스턴스화 방지

public 혹은 protected 생성자 없이 private 생성자만 정의할 경우 같은 클래스 내 main 함수에서 호출하지 않는 이상 생성자를 호출할 수 없어 인스턴스화를 방지할 수 있습니다.

같은 클래스 내 main 함수에서도 호출하는 것을 방지하고 싶을 경우 private 생성자 호출 시 AssertionError()를 반환하도록 처리하면 됩니다.


 

생성자를 private 접근 지시자로 선언했기 클래스 외부에서 생서자를 호출하는 것은 방지할 수 있었습니다.

 

 

하지만 여전히 클래스 내에서는 생성자를 호출할 수 있었습니다.

 

 

이를 방지하기 위해서는 앞서 언급했다시피 private 생성자 호출 시 AssertionError()를 반환하도록 처리하면 됩니다.

 

 

스프링 프레임워크에서는 유틸리티 클래스들을 대부분 두 번째 방법인 추상 클래스로 선언했지만 Collections과 같은 유틸성 클래스는 첫 번째 방법을 사용한 것을 확인할 수 있습니다.

 

 

마지막으로 Collections 클래스처럼 인스턴스화가 불가한 이유를 주석으로 작성해 주는 것을 습관화하면  좋을 것 같습니다.

 

방법 2. abstract 클래스로 생성하여 인스턴스화 방지

스프링 프레임워크의 유틸성 클래스는 대부분 해당 방법을 사용했는데 추상 클래스 자체는 인스턴스화할 수 없지만 해당 클래스를 상속하는 서브 클래스는 인스턴스화할 수 있다는 단점이 있습니다.

 

 

AnnotationConfigUtils도 스프링에서 제공하는 유틸성 클래스인데 두 번째 방법을 사용한 것을 확인할 수 있습니다.

 

 

이 클래스 또한 제가 굳이 상속을 해서 생성자를 호출할 경우 인스턴스화를 방지하지 못하는 것을 확인할 수 있습니다.


 

정리

인스턴스화 방지를 위해 추상 클래스를 구현하는 것보다는 private 생성자를 사용하는 방법이 더 효과적입니다.

 

참고

이펙티브 자바

이펙티브 자바 완벽 공략 1부 - 백기선 강사님

반응형