switch 支持的类型

在 Java 语言规范里中,有说明 switch 支持的类型有:char、byte、short、int、Character、Byte、Short、Integer、String、enum。

为什么不支持 long ?

为什么只支持上面几种?int、String 都可以,为什么不支持 long ?

原因就是 switch 对应的 JVM 字节码 lookupswitch、tableswitch 指令只支持 int 类型

下面是 JVM 规范中的说明(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-3.html#jvms-3.10):

byte、char、short 类型在编译期默认提升为 int,并使用 int 类型的字节码指令。所以对这些类型使用 switch,其实跟 int 类型是一样的。

为什么可以支持 String?

switch 支持 String 其实就是语法糖。编译器会根据字符串的 hashCode 来处理。

例:

String a = "aa";
switch (a) {
case "aa":
System.out.println("111");
break;
case "AaAa":
System.out.println("222");
break;
case "AaBB":
System.out.println("333");
break;
}

反编译后:

String var1 = "aa";
byte var3 = -1;
switch(var1.hashCode()) { // 第一个switch,根据hashCode计算第二个switch内的位置
case 3104:
if (var1.equals("aa")) {
var3 = 0;
}
break;
case 2031744:
if (var1.equals("AaBB")) {
var3 = 2;
} else if (var1.equals("AaAa")) {
var3 = 1;
}
} switch(var3) { // 第二个switch,执行原switch的逻辑
case 0:
System.out.println("111");
break;
case 1:
System.out.println("222");
break;
case 2:
System.out.println("333");
}

可以发现,会先根据 hashCode 找出原始 switch 内的位置,再执行原代码逻辑。

为什么用两个 switch ?

就是为了减少编译器的工作。

比如 switch 内有的 case 不写 break 等复杂情况,如果想直接根据 hashCode + equals 来只生成一个 switch,编译器就需要考虑各种情况。

所以目前编译器只做位置映射,第二部分直接按原 switch 来生成了。

关于 lookupswitch、tableswitch 可参考:你所不知道的Java之Switch

05-22 01:20