HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
[New] 타일러팀
[New] 타일러팀
/
🎾
김수미
/Effective Java 스터디/
DAY1 : 아이템 3

DAY1 : 아이템 3

Created
Apr 7, 2022 02:31 AM
Tags
📎
ITEM3 : private 생성자 혹은 enum 타입으로 싱글톤임을 보증하라

싱글톤(Singleton)

  • 인스턴스를 오직 한 개만 생성할 수 있는 클래스를 싱글톤 이라고 한다.
  • 객체 생성 요청이 여러번 발생하더라도 새롭게 메모리를 할당하여 인스턴스를 만드는 것이 아닌, 기존에 생성되어 있던 인스턴스를 참조한다.
  • 사용 예시 : Scheduling 처리 객체 등
  • 장점 : 불필요한 메모리 사용을 줄일 수 있다
  • 단점 : 이를 사용하는 클라이언트를 테스트하기 어려워 질 수 있다.
    • 싱글톤 인스턴스를 가짜(mock) 구현으로 대체할 수 없기 때문.
 

싱글톤을 만드는 두가지 방법

  • 공통점 : 생성자는 private으로, 인스턴스에 접근할 수 있는 유일한 수단 = public static 멤버
 

public static 멤버를 final 필드로 선언

public class Elvis { public static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } }
  • private Elvis 생성자는 Elvis.INSTANCE 를 생성할 때(new Elvis) 딱 한 번 호출됨
  • 다른 클래스에서 참조할 수 없는 생성자(private) 이므로 Elvis 클래스가 가지는 인스턴스는 Elvis.INSTANCE 단 한 개 뿐임을 보장할 수 있다.
  • 예외) 권한이 있는 클라이언트가 AccessibleObject.setAccessible(리플렉션 API)을 사용해 private 생성자를 호출하는 경우
    • 리플렉션 : 개발자가 클래스의 구조를 확인하거나, 값/메소드를 호출해야 할 때 사용됨 (런타임 동작 검사 및 수정에 주로 이용된다)
    • setAccessible : 필드나 메서드의 접근제어 지시자에 의한 제어를 변경하는 메서드
    • Elvis.setAccessible(true); // 이제 외부에서 private Elvis() 접근가능!
      → 방어 : 두번째 객체가 생성되려 할 때 예외를 throw 하도록 생성자 코드를 수정해야 한다.
  • 장점) 해당 클래스가 싱글톤임이 명백하게 드러나며 간결하다.
    • public static 필드가 final 이므로 절대 다른 객체를 받을 수 없기 때문
 

정적 팩토리 메서드를 public static 멤버로 제공

public class Elvis { private static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public static Elvis getInstance() { return INSTANCE; } }
  • Elvis.getInstance : 항상 같은 객체의 참조를 반환하므로 제2의 Elvis 인스턴스는 생성될 수 없음.
  • 장점 1) API를 바꾸지 않고도 싱글톤이 아니게 변경 가능 (스레드별로 다른 인스턴스를 넘겨주는 등)
  • 장점 2) 정적 팩토리 → 제네릭 싱글톤 팩토리 로 변경 가능
  • 장점 3) 정적 팩토리의 메서드 참조를 공급자(supplier)로 사용 가능
    • Elvis::getInstance 를 Supplier<Elvis>로 사용하는 식
 

싱글톤 클래스의 직렬화

  • 직렬화 : 자바 시스템 내부에서 사용되는 객체 또는 데이터들을 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술
  • 역직렬화 : 바이트로 변환된 데이터를 다시 객체로 변환하는 기술 (JVM)
  • 모든 객체 필드를 일시적(transient)이라고 선언하고 readResolve 메서드를 제공해야 함
    • 안그러면 직렬화된 인스턴스를 역직렬화할 때 마다 새로운 인스턴스가 만들어진다.
      • 예 ) 새로운 인스턴스를 생성하는 것 = 가짜 Elvis를 생성하는 것
    • 역직렬화 과정에서 만들어진 인스턴스 대신 기존에 생성된 싱글톤 인스턴스를 반환해주는 역할
public class Elvis implements Serializable { private static final Elvis INSTANCE = new Elvis(); private Elvis() { ... } public static Elvis getInstance() { return INSTANCE; } private Object readResolve() { return INSTANCE; } }
→ 싱글톤을 보장해주는 readResolve 메서드. 진짜 객체를 반환하고, 가짜 객체는 garbage collector로
 

싱글톤을 만드는 세번째 방법 : 원소가 한개인 Enum 클래스 사용하기

public enum Elvis { INSTANCE; }
→ Elvis.INSTANCE 식으로 참조 가능
  • 코드가 매우 간결하고, 또 더 쉽게 직렬화가 가능하다.
  • 복잡한 직렬화 상황 혹은 Reflection에 의해 제 2의 인스턴스가 생기는 일을 방지한다.
    • enum은 기본적으로 serializable 하기 때문에 serializable interface 를 따로 구현할 필요가 없다. 따라서 역직렬화 시에 runtime 내부에 존재하는 enum class, 즉 동일한 값을 참조한다.
    • enum class는 외부에서 액세스 할 수 있는 생성자 자체가 없으므로 reflection에 면역! (enum class 생성자 = Sole Constructor / 컴파일러에서 사용하는 것으로 사용자가 직접 호출 불가)
  • 따라서 대부분의 상황에서 Enum 선언이 싱글톤을 만드는 가장 좋은 방법이다.
    • 단, 만들고자 하는 싱글톤이 Enum 외의 클래스를 상속해야 한다면 이 방법은 사용할 수 없다.
 
싱글톤(Singleton) 패턴이란?
이번 글에서는 디자인 패턴의 종류 중 하나인 싱글톤 패턴에 대해 알아보자. 싱글톤 패턴이 무엇인지, 패턴 구현 시 주의할 점은 무엇인지에 대해 알아보는 것만으로도 많은 도움이 될 것이라 생각한다. 싱글톤(Singleton) 패턴의 정의는 단순하다. 객체의 인스턴스가 오직 1개만 생성 되는 패턴을 의미한다. 싱글톤 패턴을 사용하는 이유나 주의할 점은 조금 후에 살펴보기로 하고, 어떻게 생겼는지 그 모습을 코드로 먼저 만나보자.
싱글톤(Singleton) 패턴이란?
https://tecoble.techcourse.co.kr/post/2020-11-07-singleton/
싱글톤(Singleton) 패턴이란?
[Java] Enum의 사용법
2017/06/27 - [Java] - [Java] enum 이란? (enum 개념익히기) 이번 시간은 Enum 사용방법을 더 알아보면서 Enum에 대한 이해를 심화시켜보겠습니다. 지난 시간 공부했던 Enum에 대해서 잠시 정리하자면, 2. 서로 관련있는 상수들끼리 모아 상수들을 대표할 수 있는 이름으로 타입을 정의하는 것 3. Enum 클래스 형을 기반으로 한 클래스형 선언 정도로 요약할 수 있습니다.
[Java] Enum의 사용법
https://limkydev.tistory.com/66
[Java] Enum의 사용법
[Java & Kotlin] enum class가 완벽한 싱글톤이라 불리는 이유
싱글톤은 애플리케이션 상 특정 클래스가 최초 한 번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 디자인 패턴을 의미한다. 객체 생성 요청이 여러번 발생하더라도 새롭게 메모리를 할당하여 인스턴스를 만드는 것이 아닌 기존에 생성되어 있던 인스턴스를 참조하는 것이다. 싱글톤 패턴을 사용한다면 불필요한 메모리 사용을 줄일 수 있다는 장점이 있다.
[Java & Kotlin] enum class가 완벽한 싱글톤이라 불리는 이유
https://dataportal.kr/54
[Java & Kotlin] enum class가 완벽한 싱글톤이라 불리는 이유
[java] enum 의 serialize 에 대한 이야기
enum 은 기본적으로 serializable 하다. enum 의 serialization 은 다른 serialization 과 조금 다르다. enum 은 Enum 에 대한 class reference 만 serialize 한다. 그리고 Constant 들은 이름만 serialize 한다. 다시 말해 enum 이 변경 가능한 private field 를 가지고 있다면.. 변경된 값이 써지거나 복구되지 않는다.
[java] enum 의 serialize 에 대한 이야기
https://aroundck.tistory.com/4962
[java] enum 의 serialize 에 대한 이야기