Showing posts with label autoboxing. Show all posts
Showing posts with label autoboxing. Show all posts

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