brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Feb 22. 2018

Effective Java - 객체의 생성과 소멸

#03 private 생성자/enum 타입을 통해 싱글톤의 특성을  유지

Effective Java - 객체의 생성과 소멸


#03 private 생성자나 enum 타입을 사용해서 싱글톤의 특성을 유지하자


싱글톤(Singleton)은 하나의 인스턴스만 생성되는 클래스입니다.


싱글톤을 구현하는 방법들에 대해 알아보겠습니다.




#01. static 팩토리 메서드를 갖는 싱글톤


#01 static factory method singleton


생성자를 private로 명시해, new 키워드를 통해 인스턴스를 생성할 수 없게 합니다.

SingletonMethod instance = new SingletonMethod(); // private 접근 불가


private static final 키워드를 통해 전역 변수로 인스턴스를 생성합니다.

하지만 private 접근 제한자 때문에 인스턴스를 이용할 수 없습니다.

SingletonMethod instance = SingletonMethod.INSTANCE; // private 접근 불가


결국 getInstance 메서드를 통해서만 인스턴스를 이용할 수 있습니다.

SingletonMethod instance = SingletonMethod.getInstance();


언뜻 보면 문제가 없어 보이지만 AccessibleObject.setAccessible 메서드를 통해 private 생성자를 이용할 수 있습니다.

아래 코드를 보면 instance01은 getInstance 메서드를 통해 인스턴스를 생성했고, instance02는 리플렉션을 통해 인스턴스를 생성했습니다.

싱글톤은 항상 동일한 인스턴스를 가져야 하지만, hashCode 메서드를 통해 비교해보면 서로 다른 값을 가진 것을 알 수 있습니다.


#02 AccessibleObject.setAccessible


이를 해결하기 위해서는 아래와 같이 생성자에 INSTANCE가 이미 있는지 체크하는 로직이 필요합니다.

#03 check INSTANCE




이 외에도 직렬화(serializable) 문제도 발생할 수 있습니다.

아래와 같이 싱글톤 클래스를 직렬 화하기 위해서는 Serializable 인터페이스를 구현해야 합니다.

#04 serializable singleton


인스턴스를 직렬 화하고 다시 역질렬화하게 되면 싱글톤의 의도와 다르게 새로운 인스턴스가 생성됩니다.

#05 Serialization & Deserialization


이를 해결하기 위해서는 readResolve 메서드를 추가해야 합니다.

이 메서드는 하나의 진짜 인스턴스를 반환하고, GC가 가짜 인스턴스를 처리하도록 합니다.

#06 Add readResolve




#02. Enum 타입 싱글톤


#07 Enum singleton


Enum 타입을 이용한 싱글톤은 위에서 발생했던 리플렉션, 직렬화로 인한 문제가 전혀 없습니다.

항상 하나의 인스턴스만을 생성해 주기 때문에 구현법이 가장 간단합니다.



#08 Android studio


안드로이드 스튜디오에서는 static 팩토리 메서드를 갖는 싱글톤 방식으로 코드를 생성해주고 있습니다.

Enum 방식을 쓰지 않는 이유에 대한 공식적인 내용은 찾지 못했지만 리플렉션이나 직렬화까지 고려해서 싱글톤을 개발해야 한다면 직접 만들어야 할 거 같습니다.

매거진의 이전글 Effective Java - 객체의 생성과 소멸
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari