enum 으로 생성한 클래스 객체가 싱글톤인 이유?

enum을 이용하여 클래스를 정의하면 어떤 원리에 의해서 싱글톤으로 제공하는지, 그리고 멤버 변수가 있는데도 thread-safe한지 그 이유에 대해서 알아봤다.

public enum EnumClassTest {

INSTANCE1(“instance1”)

, INSTANCE2(“instance2”);

static {

System.out.println(“init!!”);

}

private String objName;

private EnumClassTest(String objName) {

this.objName = objName;

}

public String getObjName() {

return objName;

}

public static void main(String[] args) {

EnumClassTest[] type = EnumClassTest.values();

for (EnumClassTest enumType : type) {

System.out.println(“hashCode=” + enumType.hashCode());

System.out.println(“name=” + enumType.name());

System.out.println(“valueOf=” + EnumClassTest.valueOf(enumType.name()));

System.out.println(“ordinal=” + enumType.ordinal());

System.out.println(“declaringClass=” + enumType.getDeclaringClass());

System.out.println(“objName=” + enumType.getObjName());

System.out.println(“=====================================================”);

}

}

}

javap 명령어를 통해 클래스 파일을 원시 코드로 역어셈블하면 아래와 같은 코드가 나온다.

D:\dev\workspace\project\CardBill\target\classes\com\kyu\excel\enumtype>javap EnumClassTest

Compiled from “EnumClassTest.java”

public final class com.kyu.excel.enumtype.EnumClassTest extends java.lang.Enum<com.kyu.excel.enumtype.EnumClassTest> {

  public static final com.kyu.excel.enumtype.EnumClassTest INSTANCE1;

  public static final com.kyu.excel.enumtype.EnumClassTest INSTANCE2;

  static {};

  public java.lang.String getObjName();

  public static void main(java.lang.String[]);

  public static com.kyu.excel.enumtype.EnumClassTest[] values();

  public static com.kyu.excel.enumtype.EnumClassTest valueOf(java.lang.String);

}

중요하게 봐야 할 부분이 INSTANCE1, INSTANCE2 이다.

static final이면서 EnumClassTest type으로 선언되어 있다. 아마도 JVM에서는 EnumClassTest 초기화 시 각 상수에 있는 갯수만큼 EnumClassTest 타입의 객체를 생성하여 각 상수에 주입해 줄 것이라 예상된다.

그래서 각 상수는 싱글톤으로 생성되고, objName 멤버 변수는 thread-safe하게 유지될 수 있는 것이다.

간단하게 말해서 다음과 같이 객체를 두 번 생성한 것과 같다.

EnumClassTest INSTANCE1 = new EnumClassTest();

EnumClassTest INSTANCE2 = new EnumClassTest();

각 상수의 객체 레퍼런스가 다르 다는 것은 hashcode를 찍어보면 알 수 있다.

## INSTANCE1

hashCode=12677476

name=INSTANCE1

valueOf=INSTANCE1

ordinal=0

declaringClass=class com.kyu.excel.enumtype.EnumClassTest

objName=instance1

## INSTANCE2

hashCode=33263331

name=INSTANCE2

valueOf=INSTANCE2

ordinal=1

declaringClass=class com.kyu.excel.enumtype.EnumClassTest

objName=instance2