dk7 switch 对 String 的支持
在 jdk7 之前,switch 只能支持 byte、short、char、int 或者其对应的封装类以及 Enum 类型,在 jdk7 后,支持 String 类型。
在 switch 语句中,表达式的值不能是 null,否则会在运行时抛出 NullPointerException。在 case 子句中也不能使用 null,否则会出现编译错误。
同时,case 字句的值是不能重复的。对于字符串类型的也一样,但是字符串中可以包含 Unicode 转义字符。重复值的检查是在 Java 编译器对 Java 源代码进行相关的词法转换之后才进行的。也就是说,有些 case 字句的值虽然在源代码中看起来是不同的,但是经词法转换之后是一样的,就会在成编译错误。比如:“男” 和 “\u7537” 就是一个意思。
接下来我们就看一下,switch 到底是如何实现的。
一、switch 对整型支持的实现#
下面是一段很简单的 Java 代码,定义一个 int 型变量 a,然后使用 switch 语句进行判断。执行这段代码输出内容为 5,那么我们将下面这段代码反编译,看看他到底是怎么实现的。
public class switchDemoInt {
public static void main(String[] args) {
int a = 5;
switch (a) {
case 1:
System.out.println(1);
break;
case 5:
System.out.println(5);
break;
default:
break;
}
}
}
//output 5
反编译后的代码如下:
public class switchDemoInt
{
public switchDemoInt()
{
}
public static void main(String args[])
{
int a = 5;
switch(a)
{
case 1: // '\001'
System.out.println(1);
break;
case 5: // '\005'
System.out.println(5);
break;
}
}
}
我们发现,反编译后的代码和之前的代码比较除了多了两行注释以外没有任何区别,那么我们就知道,switch 对 int 的判断是直接比较整数的值。
二、switch 对字符型支持的实现#
直接上代码:
public class switchDemoInt {
public static void main(String[] args) {
char a = 'b';
switch (a) {
case 'a':
System.out.println('a');
break;
case 'b':
System.out.println('b');
break;
default:
break;
}
}
}
编译后的代码如下: `public class switchDemoChar
public class switchDemoChar
{
public switchDemoChar()
{
}
public static void main(String args[])
{
char a = 'b';
switch(a)
{
case 97: // 'a'
System.out.println('a');
break;
case 98: // 'b'
System.out.println('b');
break;
}
}
}
通过以上的代码作比较我们发现:对 char 类型进行比较的时候,实际上比较的是 ascii 码,编译器会把 char 型变量转换成对应的 int 型变量
三、switch 对字符串支持的实现#
还是先上代码:
public class switchDemoString {
public static void main(String[] args) {
String str = "world";
switch (str) {
case "hello":
System.out.println("hello");
break;
case "world":
System.out.println("world");
break;
default:
break;
}
}
}
对代码进行反编译:
public class switchDemoString
{
public switchDemoString()
{
}
public static void main(String args[])
{
String str = "world";
String s;
switch((s = str).hashCode())
{
default:
break;
case 99162322:
if(s.equals("hello"))
System.out.println("hello");
break;
case 113318802:
if(s.equals("world"))
System.out.println("world");
break;
}
}
}
看到这个代码,你知道原来字符串的 switch 是通过 equals()
和 hashCode()
方法来实现的。记住,switch 中只能使用整型,比如 byte
。short
,char
(ackii 码是整型) 以及 int
。还好 hashCode()
方法返回的是 int
,而不是 long
。通过这个很容易记住 hashCode
返回的是 int
这个事实。仔细看下可以发现,进行 switch
的实际是哈希值,然后通过使用 equals 方法比较进行安全检查,这个检查是必要的,因为哈希可能会发生碰撞。因此它的性能是不如使用枚举进行 switch 或者使用纯整数常量,但这也不是很差。因为 Java 编译器只增加了一个 equals
方法,如果你比较的是字符串字面量的话会非常快,比如”abc” ==”abc”。如果你把 hashCode()
方法的调用也考虑进来了,那么还会再多一次的调用开销,因为字符串一旦创建了,它就会把哈希值缓存起来。因此如果这个 switch
语句是用在一个循环里的,比如逐项处理某个值,或者游戏引擎循环地渲染屏幕,这里 hashCode()
方法的调用开销其实不会很大。
好,以上就是关于 switch 对整型、字符型、和字符串型的支持的实现方式,总结一下我们可以发现,其实 switch 只支持一种数据类型,那就是整型,其他数据类型都是转换成整型之后在使用 switch 的。
Reference#
本作品采用《CC 协议》,转载必须注明作者和本文链接