1 분 소요

Item 4. 인스턴스화를 막으려거든 private 생성자를 사용하라

인스턴스화를 막는 이유

   종종 인스턴스를 만들고 싶지 않은 클래스가 있을 수 있다. 객체지향언어에서 객체를 사용하지 않는다니 아이러니하게 들릴 수 있지만 분명 쓸모는 있다.

   상수를 정의하기 위한 용도로 사용되거나 유틸리티 클래스인 경우 인스턴스가 전혀 필요하지 않는 보조적인 클래스로 작성된다. 혹은 다른 객체를 생성해주는 팩토리 메서드를 모은 클래스일 수도 있다.

   여러 의미로 인스턴스를 만들지 못하도록 지정해야 할 때가 있는데(불필요하기 때문에) 인스턴스 생성을 방지하는 방법으로는 두 가지 정도 생각해볼 수 있다.

인스턴스화를 막는 방법

추상 클래스로 만들기

   abstract 키워드를 이용해 클래스를 추상 클래스로 정의하게 되면 해당 클래스의 생성자를 통해 인스턴스를 만들 수 없기 때문에 인스턴스화를 막을 수 있다고 생각할 수 있다. 실제로 스프링 프레임워크에서는 이 방법을 왕왕 사용하고 있다.

   그러나 추상 클래스로 만드는 것만으로는 인스턴스화를 막을 수 없다. 너무 당연하게도, 해당 클래스를 상속받은 후에 인스턴스를 만들면 그만이기 때문이다. 심지어 굳이 하위 클래스를 작성하지 않더라도 익명 클래스를 통해 인스턴스를 만들어 버릴 수도 있기 때문에 abstract 키워드만으로 인스턴스화를 막을 생각이거든 그만두는 게 좋겠다.

   그럼 또 다른 방법은 뭐가 있을까?

private 생성자

   정말 간단하게도, private 생성자를 작성하면 인스턴스화를 막을 수 있다. 정확하게는 private 외의 생성자가 존재하지 않으면 된다. private 생성자만 존재하게 되면 해당 클래스 외부에서는 생성자를 통해 인스턴스를 만들 수 없게 된다. 왜 private 생성자를 ‘작성’해야 한다고 물으신다면 대답해 드리는게 인지상정! 자바에서는 아무런 생성자를 작성하지 않게 되면 기본적으로 컴파일러가 기본 생성자를 추가하기 때문이다(이 때, 기본 생성자의 접근 제어자는 클래스의 접근 제어자를 따라간다. 즉, public 클래스일 경우에 public 기본 생성자를 생성한다). 때문에 명시적으로 private 생성자를 작성하여 기본 생성자가 생기는 것을 막야아 한다.

   하지만 private 생성자를 작성하기만 해서는 완벽하게 인스턴스화를 막을 수 없다. 왜냐하면 private 생성자도 결국은 해당 클래스 내에서는 사용 가능하기 떄문이다. 일예로 앞서 살펴보았던 싱글톤 클래스가 그러하다. 생성자는 막았지만 내부적으로 인스턴스를 만들 수 있고 그것을 메서드로 제공할 수도 있다. 그렇기에 private 생성자 내부에 Error를 발생시키거나(Exception은 개발자가 처리할 수 있는 수준이므로 Error를 발생시켜야 한다) 주석을 달아 인스턴스화를 막기 위한 생성자임을 명시해야 하는 것이 좋다. 생성자가 private이니 당연히 상속도 사용할 수 없다.


[참고]
백기선, inflearn 강의 이펙티브 자바 완벽 공략 1부
Joshua Bloch, 이펙티브 자바

<== Prev                                                Next ==>