【本文介绍】
本文主要讲java_7 的改进switch的底层实现。反编译一个使用带String的switch的demo并一步步解析反编译出来的字节码,从编译的角度解读switch的底层实现。
【正文】
在java7中,switch()可以放进去String 类型了,这无非是一大便利。底层JVM的swtich并没有真正的改进,只是在编译阶段,编译器把关于String的switch拆分成if语句而已。
我们写一个简单的例子测试一下:
(1)Test类:switch()使用String
public class Test { public void test(String str) { switch(str){ case "a": System.out.println("a");break; case "b": System.out.println("b");break; default : System.out.println("default"); } } }
(2)Test2类:switch()使用int
public class Test2 { public void test(int str) { switch(str){ case 1: System.out.println("1");break; case 2: System.out.println("2");break; default : System.out.println("default"); } } }
javac 编译 , javap -c 反编译 Test 后的结果:
1 public class Test { 2 public Test(); 3 Code: 4 0: aload_0 5 1: invokespecial #1 // Method java/lang/Object."<init>": 6 ()V 7 4: return 8 9 public void test(java.lang.String); 10 Code: 11 0: aload_1 12 1: astore_2 ---------------从这里开始------------ 13 2: iconst_m1 // 将int型-1推送至栈顶 14 3: istore_3 // 赋值,因为此时栈顶元素为-1,所以赋值-1 15 4: aload_2 16 5: invokevirtual #2 // Method java/lang/String.hashCode: 调用hasCode方法 17 ()I 18 8: lookupswitch { // 2 源码本来只有一次switch,现在被拆分成两次,这是第一次switch,下面还有一次公共的 19 97: 36 case 97 : 跳至36行 aload_2 20 98: 50 case 98 :跳至50行 aload_2 21 default: 61 default : 跳至61行 iload_3 22 } 23 36: aload_2 24 37: ldc #3 // String a 下面equal的内容 25 39: invokevirtual #4 // Method java/lang/String.equals:(L 进行equal的比较 26 java/lang/Object;)Z 27 42: ifeq 61 // if 语句 28 45: iconst_0 // 将int型0推送至栈顶 29 46: istore_3 // 赋值,因为此时栈顶元素为 0 ,所以赋值0 30 47: goto 61 31 50: aload_2 32 51: ldc #5 // String b 下面equal的内容 33 53: invokevirtual #4 // Method java/lang/String.equals:(L 进行equal的比较 34 java/lang/Object;)Z 35 56: ifeq 61 // if 语句 36 59: iconst_1 // 将int型1推送至栈顶 37 60: istore_3 // 赋值,因为此时栈顶元素为 1 , 所以赋值1 38 61: iload_3 ----------------到这里结束--------------- 39 62: lookupswitch { // 2 40 0: 88 41 1: 99 42 default: 110 43 } 44 88: getstatic #6 // Field java/lang/System.out:Ljava/ 45 io/PrintStream; 46 91: ldc #3 // String a 47 93: invokevirtual #7 // Method java/io/PrintStream.printl 48 n:(Ljava/lang/String;)V 49 96: goto 118 50 99: getstatic #6 // Field java/lang/System.out:Ljava/ 51 io/PrintStream; 52 102: ldc #5 // String b 53 104: invokevirtual #7 // Method java/io/PrintStream.printl 54 n:(Ljava/lang/String;)V 55 107: goto 118 56 110: getstatic #6 // Field java/lang/System.out:Ljava/ 57 io/PrintStream; 58 113: ldc #8 // String default 59 115: invokevirtual #7 // Method java/io/PrintStream.printl 60 n:(Ljava/lang/String;)V 61 118: return 62 }
javac 编译 , javap -c 反编译 Test2 后的结果:
1 public class Test2 { 2 public Test2(); 3 Code: 4 0: aload_0 5 1: invokespecial #1 // Method java/lang/Object."<init>": 6 ()V 7 4: return 8 9 public void test(int); 10 Code: 11 0: iload_1 12 1: lookupswitch { // 2 13 1: 28 14 2: 39 15 default: 50 16 } 17 28: getstatic #2 // Field java/lang/System.out:Ljava/ 18 io/PrintStream; 19 31: ldc #3 // String 1 20 33: invokevirtual #4 // Method java/io/PrintStream.printl 21 n:(Ljava/lang/String;)V 22 36: goto 58 23 39: getstatic #2 // Field java/lang/System.out:Ljava/ 24 io/PrintStream; 25 42: ldc #5 // String 2 26 44: invokevirtual #4 // Method java/io/PrintStream.printl 27 n:(Ljava/lang/String;)V 28 47: goto 58 29 50: getstatic #2 // Field java/lang/System.out:Ljava/ 30 io/PrintStream; 31 53: ldc #6 // String default 32 55: invokevirtual #4 // Method java/io/PrintStream.printl 33 n:(Ljava/lang/String;)V 34 58: return 35 }
大家看到这么多字节码是不是有点头晕不想再看下去了?其实只需稍稍观察比较就能发现”从这里开始“——”到这里结束“中间那些字节码是下面那个字节码文件所没有的,所以我们研究这几行代码就行了。又看我用红色字体标出来的注释,结果就显而易见了:
(0)用一个int类型变量代表String类型变量
(1)获取String字符串的hashCode
(2)case hashCode
(3)用if语句处理String
(4)为int类型的变量赋值
(5)真正的swtich,现在传入的是上面得出的int类型变量。
把上面的字节码文件翻译成java即:
1 public class test { 2 3 public void test(String str) { 4 5 int i = -1; 6 7 switch(str.hashCode()){ 8 9 case 97: 10 if(str.equals("a")){ 11 i = 0; 12 } 13 break; 14 case 98: 15 if(str.equals("b")){ 16 break; 17 } 18 } 19 20 switch(i) { 21 22 case 0: 23 System.out.println("a"); 24 break; 25 26 case 1: 27 System.out.println("b"); 28 break; 29 30 default: 31 System.out.println("default"); 32 } 33 } 34 }
java7(1)——反编译深入理解增强的switch,布布扣,bubuko.com
时间: 2024-11-25 05:57:51