java invokevirtual_java7(1)——反编译深入理解增强的switch

【本文介绍】

本文主要讲java_7 的改进switch的底层实现。反编译一个使用带String的switch的demo并一步步解析反编译出来的字节码,从编译的角度解读switch的底层实现。

【正文】

在java7中,switch()可以放进去String 类型了,这无非是一大便利。底层JVM的swtich并没有真正的改进,只是在编译阶段,编译器把关于String的switch拆分成if语句而已。

我们写一个简单的例子测试一下:

(1)Test类:switch()使用String

public classTest {public voidtest(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 classTest2 {public void test(intstr) {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 classTest {2 publicTest();3 Code:4 0: aload_05 1: invokespecial #1 //Method java/lang/Object."":

6 ()V7 4: return

8

9 public voidtest(java.lang.String);10 Code:11 0: aload_112 1: astore_2                ---------------从这里开始------------13 2: iconst_m1              // 将int型-1推送至栈顶14 3: istore_3               // 赋值,因为此时栈顶元素为-1,所以赋值-115 4: aload_216 5: invokevirtual #2 //Method java/lang/String.hashCode: 调用hasCode方法

17 ()I18 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_224 37: ldc #3 //String a  下面equal的内容

25 39: invokevirtual #4 // Method java/lang/String.equals:(L  进行equal的比较

26 java/lang/Object;)Z27 42: ifeq 61           // if 语句

28 45: iconst_0               // 将int型0推送至栈顶29 46: istore_3               // 赋值,因为此时栈顶元素为 0 ,所以赋值030 47: goto 61

31 50: aload_232 51: ldc #5 //String b 下面equal的内容

33 53: invokevirtual #4 // Method java/lang/String.equals:(L进行equal的比较

34 java/lang/Object;)Z35 56: ifeq 61           // if 语句

36 59: iconst_1               // 将int型1推送至栈顶37 60: istore_3               // 赋值,因为此时栈顶元素为 1 , 所以赋值138 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;)V49 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;)V55 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;)V61 118: return

62 }

javac 编译 , javap -c 反编译 Test2 后的结果:

1 public classTest2 {2 publicTest2();3 Code:4 0: aload_05 1: invokespecial #1 //Method java/lang/Object."":

6 ()V7 4: return

8

9 public void test(int);10 Code:11 0: iload_112 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;)V22 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;)V28 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;)V34 58: return

35 }

大家看到这么多字节码是不是有点头晕不想再看下去了?其实只需稍稍观察比较就能发现”从这里开始“——”到这里结束“中间那些字节码是下面那个字节码文件所没有的,所以我们研究这几行代码就行了。又看我用红色字体标出来的注释,结果就显而易见了:

(0)用一个int类型变量代表String类型变量

(1)获取String字符串的hashCode

(2)case hashCode

(3)用if语句处理String

(4)为int类型的变量赋值

(5)真正的swtich,现在传入的是上面得出的int类型变量。

把上面的字节码文件翻译成java即:

1 public classtest {2

3 public voidtest(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 }

原文:http://www.cnblogs.com/xiaoMzjm/p/3885990.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值