Java中字符串String Switch的实现原理

Switch能否用String做参数?   参数可以是整数表达式,JDK1.5开始支持Enum类,JDK1.7开始支持String。

对这个感兴趣还有一个原因,是我想在面试中问一下这个问题,如果面试中有类似这样的一个问题的话会非常有趣。验证它其实非常简单,你只需用字符串写一段switch的代码,然后反编译一下,看看编译器是如何翻译它们的就可以了。


原始代码:

这是一个简单的测试程序,它有一个main方法,里面有一个switch块在操作String变量。程序中用到的字符串参数是运行时传递进来的,你可以从main方法的字符串数组中获取到。有三种模式来启动这个程序,主动模式,被动模式,以及安全模式。对于这些已知的确定值,其实用枚举来实现要更好,但如果你已经决定使用字符串了,你得确保你写的是大写的,不要写成小成或者骆驼式的,这样会出现大小写敏感的问题。

  1. public class StringInSwitchCase {   
  2.       public static void main(String[] args) {   
  3.             String mode = args[0];   
  4.             switch (mode) {   
  5.                   case "ACTIVE":   
  6.                         System.out.println("Application is running on Active mode");   
  7.                         break;   
  8.                   case "PASSIVE":  
  9.                         System.out.println("Application is running on Passive mode");   
  10.                          break;   
  11.                   case "SAFE":   
  12.                           System.out.println("Application is running on Safe mode");   
  13.           }   
  14.       }   
  15. }  
hashcode返回的是int型
可以发现:进行switch的实际是hash值,然后用equals进行安全检查(因为hash值可能会发生碰撞),所以性能不如枚举。switch支持String其实是一个语法糖,在编译后的字节码文件中都会被还原成原生类型,并在相应位置插入了强制转换代码,底层的JVM在switch上并没有修改。

当传入switch的是null时,在运行时对一个null调用hashCode()方法,会抛出NullPointerException;如果case写的是null,那么在编译时无法求出hashcode,就会编译报错。

  1. import java.io.PrintStream;   
  2.   
  3. public class StringInSwitchCase{   
  4.       public StringInSwitchCase() { }   
  5.   
  6.       public static void main(string args[]) {   
  7.              String mode = args[0];   
  8.             String s; switch ((s = mode).hashCode()) {   
  9.                   defaultbreak;   
  10.                   case -74056953:   
  11.                         if (s.equals("PASSIVE")) {   
  12.                                     System.out.println("Application is running on Passive mode");   
  13.                          }   
  14.                         break;   
  15.                   case 2537357:   
  16.                         if (s.equals("SAFE")) {   
  17.                               System.out.println("Application is running on Safe mode");   
  18.                          }   
  19.                         break;   
  20.                   case 1925346054:   
  21.                         if (s.equals("ACTIVE")) {   
  22.                               System.out.println("Application is running on Active mode");   
  23.                          }   
  24.                         break;   
  25.                }   
  26.           }   
  27. }  

        看到这个代码,你知道原来字符串的switch是通过equals和hashCode()方法来实现的。

        记住,switch中只能使用整型,比如byte。short,char以及int。还好hashCode()方法返回的是int,而不是long。

        通过这个很容易记住hashCode返回的是int这个事实,事实上我自己都会经常忘了或者弄混。仔细看下可以发现,进行

switch的实际是哈希值,然后通过使用equals方法比较进行安全检查,这个检查是必要的,因为哈希可能会发生碰撞。

注意

1.整数表达式可以是int和Integer,而byte、short、char等可以转换成int,所以也可以用。但是long和String不能转换成int,所以不能用

2.String时不能传入null作为参数,同时case语句中使用的字符串也不能为null,因为底层是通过equals和hashmap来判断的

文章参考原文:第一篇  第二篇


小伙伴们可以关注我的公众号,留言必回复哦


Java核心基础

----------------------------------

长按关注哦(看那两撇小胡子)

基础 | 心得 | 经历 | 更重要的是开心嘛!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值