Java7中的switch支持String的实现细节

作者: zsxwing 更新: 2013-03-04 21:08:02 发布: 2012-04-26 13:58:19

在Java7之前,switch只能支持 byte、short、char、int或者其对应的封装类以及Enum类型。在Java7中,呼吁很久的String支持也终于被加上了。
 
例如,下面是一段switch中使用String的示例代码。

 public class Test {

     public void test(String str) {
switch(str) {
case "abc":
System.out.println("abc");
break;
case "def":
System.out.println("def");
break;
default:
System.out.println("default");
}
} }
 
 
在switch语句中,String的比较用的是String.equals,因此大家可以放心的使用。
需要注意的是,传给switch的String变量不能为null,同时switch的case子句中使用的字符串也不能为null。
为什么要有这些非null的限制呢?其实,我们只要将这段代码反汇编出来,看一下底层到底是如何实现的,就可以明白了。下面是汇编出来的代码。
 
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
  Code:
   0:     aload_0
   1:     invokespecial     #1; //Method java/lang/Object."":()V
   4:     return
 
public void test(java.lang.String);
  Code:
   0:     aload_1
   1:     astore_2
   2:     iconst_m1
   3:     istore_3
   4:     aload_2
   5:     invokevirtual     #2; //Method java/lang/String.hashCode:()I
   8:     lookupswitch{ //2
          96354: 36;
          99333: 50;
          default: 61 }
   36:     aload_2
   37:     ldc     #3; //String abc
   39:     invokevirtual     #4; //Method java/lang/String.equals:(Ljava/lang/Object;)Z
   42:     ifeq     61
   45:     iconst_0
   46:     istore_3
   47:     goto     61
   50:     aload_2
   51:     ldc     #5; //String def
   53:     invokevirtual     #4; //Method java/lang/String.equals:(Ljava/lang/Object;)Z
   56:     ifeq     61
   59:     iconst_1
   60:     istore_3
   61:     iload_3
   62:     lookupswitch{ //2
          0: 88;
          1: 99;
          default: 110 }
   88:     getstatic     #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   91:     ldc     #3; //String abc
   93:     invokevirtual     #7; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   96:     goto     118
   99:     getstatic     #6; //Field java/lang/System.out:Ljava/io/PrintStream;
   102:     ldc     #5; //String def
   104:     invokevirtual     #7; //Method java/io/PrintStream.println:(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.println:(Ljava/lang/String;)V
   118:     return
 
}
 
估计有些同学懒得看这些汇编,其实把上面的汇编代码用Java写出来就是下面的样子了。
写到这里,大家应该能明白为什么不能用null了吧。
 
 public class Test {
public void test(String str) {
int i = -1;
switch(str.hashCode()) {
case 96354: // "abc".hashCode()
if (str.equals("abc")) {
i = 0;
}
break;
case 99333: // "def".hashCode()
if (str.equals("def")) {
i = 1;
}
break;
default:
break;
} switch(i) {
case 0:
System.out.println("abc");
break;
case 1:
System.out.println("def");
break;
default:
System.out.println("default");
}
}
}
 
如果switch传入的null,那么在运行时对一个null对象调用hashCode方法会出现NullPointerException。
如果switch的case写的是null,那么在编译时无法求出hashCode,因此在编译时就会报错了。
 
switch支持String只是一个语法糖,由javac来负责生成相应的代码。底层的JVM在switch上并没有进行修改。
 
参考
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
 
如果switch传入的null,那么在运行时对一个null对象调用hashCode方法会出现NullPointerException。
如果switch的case写的是null,那么在编译时无法求出hashCode,因此在编译时就会报错了。
 
switch支持String只是一个语法糖,由javac来负责生成相应的代码。底层的JVM在switch上并没有进行修改。
 

Java jre7及以上版本中的switch支持String的实现细节的更多相关文章

  1. java中的switch用String作为条件

    在开发java程序的过程中,我们遇到了条件推断首选就是switch,可是java中的switch功能不支持字符串作为条件.这时我们该怎么办呢? --使用枚举. 一.枚举简单了解    1.enum是一 ...

  2. idea中,发现某个java语法在低版本中不支持时的解决办法

    比如,在某个工程中,准备用java.util.Objects#equals语法,发现提示版本不支持. F4查看Module的配置,发现原来是1.6版本. 当我手动修改为1.8时,提示我:Module是 ...

  3. JDK1.7之后switch支持string

    转自:https://blog.csdn.net/tjcyjd/article/details/9666035 在Java7之前,switch只能支持 byte.short.char.int或者其对应 ...

  4. IOS中多版本,多设备类型支持注意事项

    IOS系统从07年出来,到现在也有6年了,每年发布一次到两次新的设备,从iPhone1,iPhone2 ... iPhone4s再到最新的iPhone5.硬件在升级的过程中CPU的架构也可能发生变化, ...

  5. [译] OpenStack Ocata 版本中的 53 个新功能盘点

    原文链接:https://www.mirantis.com/blog/53-new-things-to-look-for-in-openstack-ocata/ 原文作者:Nick Chase, Ra ...

  6. IDEA使用switch传入String编译不通过

    今天在使用IDEA的时候,用到switch分支语句,传入String参数的时候一直报错,下面是源码报错截图: 看错误提示并没有提到switch支持String类型,不过ava1.7之后就支持Strin ...

  7. Java 7 中的Switch 谈 Java版本更新和反编译知识

    Java 7 中的Switch 谈 Java版本更新和反编译知识          学习编程,享受生活,大家好,我是追寻梦的飞飞.今天主要讲述的是Java7中的更新Switch实现内部原理和JAD反编 ...

  8. Java 14中对switch的增强,终于可以不写break了

    面对这样的if语句,你是不是很难受呢? if (flag == 1) { log.info("didispace.com: 1"); } else if (flag == 2) { ...

  9. java中的Switch case语句

    java中的Switch case 语句 在Switch语句中有4个关键字:switch,case break,default. 在switch(变量),变量只能是整型或者字符型,程序先读出这个变量的 ...

随机推荐

  1. linux下安装并配置vim

    1.安装:sudo apt-get install vim-gtk  安装好后vim,并按“tab”键,可以看到vim的存在,则安装好2.设置更加人性化:sudo vim /etc/vim/vimrc ...

  2. 微軟将弃用 System.Data.OracleClient

    http://www.cnblogs.com/WizardWu/archive/2010/05/17/1737009.html 微軟将从 .NET 4 以后的版本弃用 System.Data.Orac ...

  3. 【ora10,4】oracle后台进程介绍:

    一.SMON(System MONitor) 系统监控进程:      在数据库启动过程中,SMON排在CKPT进程之后,在Oracle9i中排在第六号的位置: PMON started with p ...

  4. sgu101Domino

    给你一些边,假设存在欧拉路径就打出来 我的代码例如以下: #include<iostream> #include<cstring> using namespace std; i ...

  5. LeetCode 451. Sort Characters By Frequency (根据字符出现频率排序)

    Given a string, sort it in decreasing order based on the frequency of characters. Example 1: Input: ...

  6. web的自己主动化公布

    </pre>基于眼下业务的版本号.使用的maven 及tomcat <p></p><p>假设我们使用 Jenkins 公布是比較好的,可是存在一定的问题 ...

  7. ES6 一些常用使用

    //1.解构数组 let arr1 = ['apple', 'coffee', 'cake']; let [fruit, drink, dessert] = arr1; console.log(fru ...

  8. Android资源之图像资源(图像级别资源)

    图像状态资源仅仅能定义有限的几种状态. 假设须要很多其它的状态,就要使用图像级别资源. 在该资源文件里能够定义随意多个图像级别. 每一个图像级别是一个整数区间,能够通过ImageView.setIma ...

  9. oc71--NSArray2

    // // Person.h #import <Foundation/Foundation.h> @interface Person : NSObject - (void)say; - ( ...

  10. 超级有用的git reset --hard和git revert命令

    很多时候,git新手容易误操作,比如,在levelIISZ-1.4.dev分支下,运行了git pull idc cpp-1.0的结果,这样做麻烦很大,经常导致maven项目格式不正确,这个时候,可以 ...