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