Saturday, September 26, 2009

The Curious Case of Enums and Autoboxing

Prior to the release of JDK 5, the expression in a switch statement must be either a char, byte, short, or int; otherwise, compilation error occurs.

 switch (expression) { 
...
}


However as of JDK 5, Sun introduced enumeration type and auto-boxing and because of this, the switch statement also supports these two concepts.

Below is sample code for JDK 5 and later:

1:  public class CaseEnum {  
2: enum ResultEnum { OK, CANCEL };
3: public void test1() {
4: ResultEnum result = ResultEnum.OK;
5: switch (result) {
6: case OK:
7: case CANCEL:
8: }
9: }
10: public void test2() {
11: switch (new Integer(2)) {
12: case 1:
13: case 2:
14: }
15: }
16: public void test3() {
17: switch (new Byte((byte) 3)) {
18: case 1:
19: case 2:
20: case 3:
21: }
22: }
23: }


Compiling with JDK6 and disassembling this class reveals:

1:  Compiled from "CaseEnum.java"  
2: public class CaseEnum extends java.lang.Object{
3: public CaseEnum();
4: Code:
5: 0: aload_0
6: 1: invokespecial #1; //Method java/lang/Object."<init>":()V
7: 4: return
8: public void test1();
9: Code:
10: 0: getstatic #2; //Field CaseEnum$ResultEnum.OK:LCaseEnum$ResultEnum;
11: 3: astore_1
12: 4: getstatic #3; //Field CaseEnum$1.$SwitchMap$CaseEnum$ResultEnum:[I
13: 7: aload_1
14: 8: invokevirtual #4; //Method CaseEnum$ResultEnum.ordinal:()I
15: 11: iaload
16: 12: lookupswitch{ //2
17: 1: 40;
18: 2: 40;
19: default: 40 }
20: 40: return
21: public void test2();
22: Code:
23: 0: new #5; //class java/lang/Integer
24: 3: dup
25: 4: iconst_2
26: 5: invokespecial #6; //Method java/lang/Integer."<init>":(I)V
27: 8: invokevirtual #7; //Method java/lang/Integer.intValue:()I
28: 11: lookupswitch{ //2
29: 1: 36;
30: 2: 36;
31: default: 36 }
32: 36: return
33: public void test3();
34: Code:
35: 0: new #8; //class java/lang/Byte
36: 3: dup
37: 4: iconst_3
38: 5: invokespecial #9; //Method java/lang/Byte."<init>":(B)V
39: 8: invokevirtual #10; //Method java/lang/Byte.byteValue:()B
40: 11: tableswitch{ //1 to 3
41: 1: 36;
42: 2: 36;
43: 3: 36;
44: default: 36 }
45: 36: return
46: }


From line 14, javac adds an extra command to turn the enum into an integer value by invoking the enum "ordinal" method: CaseEnum$ResultEnum.ordinal:()I

From line 27, javac adds an extra command to unbox Integer to int by invoking the "intValue" method:
java/lang/Integer.intValue:()I

From line 39, again javac adds another extra command to unbox Byte to byte by invoking the "byteValue" method:
java/lang/Byte.byteValue:()B

No comments:

Post a Comment