【本文介绍】

  本文主要讲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 后的结果:

public class Test {
public Test();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":
()V
4: return public void test(java.lang.String);
Code:
0: aload_1
1: astore_2                ---------------从这里开始------------
2: iconst_m1              // 将int型-1推送至栈顶
3: istore_3               // 赋值,因为此时栈顶元素为-1,所以赋值-1
4: aload_2
5: invokevirtual #2 // Method java/lang/String.hashCode: 调用hasCode方法
()I
8: lookupswitch { // 2        源码本来只有一次switch,现在被拆分成两次,这是第一次switch,下面还有一次公共的
97: 36           case 97 : 跳至36行 aload_2
98: 50           case 98 :跳至50行 aload_2
default: 61           default : 跳至61行 iload_3
}
36: aload_2
37: ldc #3 // String a  下面equal的内容
39: invokevirtual #4 // Method java/lang/String.equals:(L  进行equal的比较
java/lang/Object;)Z
42: ifeq 61           // if 语句
45: iconst_0               // 将int型0推送至栈顶
46: istore_3               // 赋值,因为此时栈顶元素为 0 ,所以赋值0
47: goto 61
50: aload_2
51: ldc #5 // String b 下面equal的内容
53: invokevirtual #4 // Method java/lang/String.equals:(L  进行equal的比较
java/lang/Object;)Z
56: ifeq 61           // if 语句
59: iconst_1               // 将int型1推送至栈顶 
60: istore_3               // 赋值,因为此时栈顶元素为 1 , 所以赋值1
61: iload_3                ----------------到这里结束---------------
62: lookupswitch { //
0: 88
1: 99
default: 110
}
88: getstatic #6 // Field java/lang/System.out:Ljava/
io/PrintStream;
91: ldc #3 // String a
93: invokevirtual #7 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
96: goto 118
99: getstatic #6 // Field java/lang/System.out:Ljava/
io/PrintStream;
102: ldc #5 // String b
104: invokevirtual #7 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
107: goto 118
110: getstatic #6 // Field java/lang/System.out:Ljava/
io/PrintStream;
113: ldc #8 // String default
115: invokevirtual #7 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
118: return
}

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

public class Test2 {
public Test2();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":
()V
4: return public void test(int);
Code:
0: iload_1
1: lookupswitch { //
1: 28
2: 39
default: 50
}
28: getstatic #2 // Field java/lang/System.out:Ljava/
io/PrintStream;
31: ldc #3 // String 1
33: invokevirtual #4 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
36: goto 58
39: getstatic #2 // Field java/lang/System.out:Ljava/
io/PrintStream;
42: ldc #5 // String 2
44: invokevirtual #4 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
47: goto 58
50: getstatic #2 // Field java/lang/System.out:Ljava/
io/PrintStream;
53: ldc #6 // String default
55: invokevirtual #4 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
58: return
}

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

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

(1)获取String字符串的hashCode

(2)case hashCode

(3)用if语句处理String

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

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

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

 public class test {

     public void test(String str) {

         int i = -1;

         switch(str.hashCode()){

         case 97:
if(str.equals("a")){
i = 0;
}
break;
case 98:
if(str.equals("b")){
break;
}
} switch(i) { case 0:
System.out.println("a");
break; case 1:
System.out.println("b");
break; default:
System.out.println("default");
}
}
}

java7(1)——反编译深入理解增强的switch(读字节命令实战)的更多相关文章

  1. 通过反编译深入理解Java String及intern(转)

    通过反编译深入理解Java String及intern 原文传送门:http://www.cnblogs.com/paddix/p/5326863.html 一.字符串问题 字符串在我们平时的编码工作 ...

  2. 通过反编译深入理解Java String及intern

    一.字符串问题 字符串在我们平时的编码工作中其实用的非常多,并且用起来也比较简单,所以很少有人对其做特别深入的研究.倒是面试或者笔试的时候,往往会涉及比较深入和难度大一点的问题.我在招聘的时候也偶尔会 ...

  3. (转)通过反编译深入理解Java String及intern

    原文链接:https://www.cnblogs.com/paddix/p/5326863.html 一.字符串问题 字符串在我们平时的编码工作中用的非常多,并且用起来非常简单,所以很少有人对其做特别 ...

  4. 从反编译深入理解JAVA内部类类结构以及finalkeyword

    1.为什么成员内部类能够无条件訪问外部类的成员? 在此之前,我们已经讨论过了成员内部类能够无条件訪问外部类的成员,那详细到底是怎样实现的呢?以下通过反编译字节码文件看看到底.其实,编译器在进行编译的时 ...

  5. android apk 防止反编译技术第二篇-运行时修改字节码

    上一篇我们讲了apk防止反编译技术中的加壳技术,如果有不明白的可以查看我的上一篇博客http://my.oschina.net/u/2323218/blog/393372.接下来我们将介绍另一种防止a ...

  6. Java| 编译和反编译

    原文链接: http://www.yveshe.com/articles/2018/05/01/1525172129089.html 什么是编程语言? 在介绍编译和反编译之前,我们先来简单介绍下编程语 ...

  7. Java 编译与反编译

    编程语言 在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language).编程语言(Programming Language)分为低级语言(Low-level Lang ...

  8. JD-GUI反编译后代码逻辑分析

    一,用jd-gui.exe等工具查看源代码.如何你不会,可以参看此文章: http://blog.csdn.net/hp_2008/article/details/8207879 可以到以下连接下载可 ...

  9. apk 反编译工具的使用

    在学习android 开发的时候,我们经常回尝试使用到别人的apk,希望能了解别人怎么编写的代码,于是想要一个能实现其反编译的软件,将软件反编译出来,查看其代码. 工具/原料 反编译软件dex2jar ...

随机推荐

  1. 修改ElasticSearch默认的from size

    2016年04月07日 17:04:17 阅读数:8065 如果需要搜索分页,可以通过from size组合来进行.from表示从第几行开始,size表示查询多少条文档.from默认为0,size默认 ...

  2. c配置库ccl使用小结

    配置文件为key=value键值对形式 下载与安装 库文件下载:ccl-0.1.1.tar.gz 安装:  tar -zxvf ccl-0.1.1.tar.gz  cd ccl-0.1.1 ./con ...

  3. 概率论 - BZOJ - 4001 TJOI2015

    TJOI2015 Problem's Link ---------------------------------------------------------------------------- ...

  4. SQL Server 2012附加数据库报错

    操作系统: win8 数据库:SQL 2012 遇到问题: 以管理员身份登录SQL 2012,附件数据库提示如下错误: 解决办法: 以windows账号登录,附加,成功!

  5. [工具使用] 如何访问github

    1.ping github.com,记录github的ip:192.30.252.129 2.找到系统的 hosts文件位置: C:\Windows\System32\drivers\etc\host ...

  6. pycharm Tab键设置成4个空格

    file--->setting,选择Editor--->python,如下图所示:

  7. git error Another git process seems to be running in this repository

    How to fix error Another git process seems to be running in this repository When you use Git, you se ...

  8. OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言,使页面更简洁;

    OGNL(Object-Graph Navigation Language),可以方便地操作对象属性的开源表达式语言,使页面更简洁: 支持运算符(如+-*/),比普通的标志具有更高的自由度和更强的功能 ...

  9. (转)内核container_of(ptr,type,member) 解析

     container_of(ptr,type,member) 用于在已知结构体里面成员member和该成员指针ptr(就是地址)和结构体类型type, 返回该成员所在的结构体的指针(就是地址), 例如 ...

  10. hrbustoj 1306:再遇攻击(计算几何,判断点是否在多边形内,水题)

    再遇攻击 Time Limit: 1000 MS    Memory Limit: 65536 K Total Submit: 253(37 users)   Total Accepted: 56(2 ...