switch可以进行跳转优化,java中对switch有两种处理方式,生成不同的jvm指令,一是tableswitch,一个是lookupswitch.
对于case的分支比较密集的情况,如
Java code
public class Test { public static void main(String[] args) { int i = 3; switch (i) { case 0: System.out.println("0"); break; case 1: System.out.println("1"); break; case 3: System.out.println("3"); break; case 5: System.out.println("5"); break; case 10: System.out.println("10"); break; case 13: System.out.println("13"); break; case 14: System.out.println("14"); break; default: System.out.println("default"); break; } }}

使用tableswitch,得到
< dl class="code" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; width: 718px; overflow-x: auto; overflow-y: auto; font-size: 12px; ">
Java code
public static void main(java.lang.String[]); Code: 0: iconst_3 1: istore_1 2: iload_1 3: tableswitch{ //0 to 14 0: 76; 1: 87; 2: 153; 3: 98; 4: 153; 5: 109; 6: 153; 7: 153; 8: 153; 9: 153; 10: 120; 11: 153; 12: 153; 13: 131; 14: 142; default: 153 } 76: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 79: ldc #3; //String 0 81: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 84: goto 161 87: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 90: ldc #5; //String 1 92: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 95: goto 161 98: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 101: ldc #6; //String 3 103: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 106: goto 161 109: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 112: ldc #7; //String 5 114: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 117: goto 161 120: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 123: ldc #8; //String 10 125: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 128: goto 161 131: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 134: ldc #9; //String 13 136: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 139: goto 161 142: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 145: ldc #10; //String 14 147: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 150: goto 161 153: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 156: ldc #11; //String default 158: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 161: return}

从中可以看到tableswitch使用的跳转表。它这样查找,如果case值不在//0 to 14之间,直接执行default,如果在此范围之内,则取目标值-0这一项作为目标,比如switch(i),i为3,则跳转到3-0=3,使用数组中的第三项作为目标,也就是3: 98;直接去执行98行。

如果case中的值比较稀疏,则使用lookupswitch:
Java code
public class Test2 { public static void main(String[] args) { int i = 3; switch (i) { case 3: System.out.println("3"); break; case 20: System.out.println("20"); break; case 50: System.out.println("50"); break; case 100: System.out.println("100"); break; } }}

编译为
Java code
public static void main(java.lang.String[]); Code: 0: iconst_3 1: istore_1 2: iload_1 3: lookupswitch{ //4 3: 44; 20: 55; 50: 66; 100: 77; default: 85 } 44: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 47: ldc #3; //String 3 49: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 52: goto 85 55: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 58: ldc #5; //String 20 60: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 63: goto 85 66: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 69: ldc #6; //String 50 71: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 74: goto 85 77: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 80: ldc #7; //String 100 82: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 85: return

可以看到其中的
 3: lookupswitch{ //4
3: 44;
20: 55;
50: 66;
100: 77;
default: 85 }
这个就要挨着查表确定跳转位置了。