在jDK1.6之前传到switch这个关键词里面的参数只能是char和int类型的数据,但是JDK1.7之后,传进switch里面的值可以是String类型。
之前用的时候一直没有想过这个问题,今天有空就一起探索一下这个问题。
我们先看一下传进switch的值为int类型的代码:
int number = 5;
switch(number)
{
case 'c':
System.out.println("the case number is c");
break;
case 22:
System.out.println("the case number is 2");
break;
}
将之编译成class文件然后反编译,看这段代码会是怎样的:
int number = 5;
switch (number)
{
case 99:
System.out.println("the case number is c");
break;
case 22:
System.out.println("the case number is 2");
}
可以知道,字符‘c’被编译成了99.这个很容易理解,我们都知道在字符'c'按照Ascii编码规范,‘c’的二进制编码为01100011,转换为十进制就是99.看到这个可能会想,如果跟在case后面的char的二进制和其它case的int相同,会发生什么效果呢?刚试了一下,直接导致的是编译不通过。你们也可以试一下传进去一个char值,看会发生什么问题
char c ='1';
switch(c)
{
case 'c':
System.out.println();
break;
case 0:
System.out.println();
break;
default:
}
反编译代码为:
char c = '1';
switch (c)
{
case 'c':
System.out.println();
break;
case '\000':
System.out.println();
}
对比两段代码,我们不难发现,case后面跟的常量编译之后的形式与switch传进去的值有关,当传进去的是int类型,case后面的常量肯定也会编译成int类型,即使有char类型也会被编译转换为int类型。如果是char类型,则会转换为char类型。
下面我们看一下JDK1.7的switch新特性,如果传进去的是String类型,编译过后的代码是怎样的呢,jdk1.7这个新加的特性,是通过修改jvm还是怎么实现的呢。
我们看一下这段代码:
String str = "123";
switch(str)
{
case "123":
System.out.println(str);
break;
case "456":
System.out.println(str);
break;
default:
System.out.println(str);
}
编译之后,反编译得代码如下:
String str = "123";
String str1;
switch ((str1 = str).hashCode())
{
case 48690:
if (str1.equals("123")) {
break;
}
break;
case 51669:
if (!str1.equals("456"))
{
break label80;
System.out.println(str);
break label87;
}
else
{
System.out.println(str);
}
break;
}
我们可以看到,其实传进switch的是字符串的hashCode值,而case 后面的字符串常量在编译之后也变成了它的hashCode。而在case后面的模块代码中多了一段比较case后面的字符串常量与传进来的字符串是否相等的判断代码。
在此我们可以看出,jdk1.7的switch新特性,case的常量可以是字符串,传进去的值可以是字符串,其实也是沿用之前的特性,只是在编译的时候将字符串转换为hashcode值对比而已