Java7中的switch支持String的实现细节
2014-11-30 17:31
435 查看
在Java7之前,switch只能支持 byte、short、char、int或者其对应的封装类以及Enum类型。在Java7中,呼吁很久的String支持也终于被加上了。
例如,下面是一段switch中使用String的示例代码。
在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了吧。
如果switch传入的null,那么在运行时对一个null对象调用hashCode方法会出现NullPointerException。
如果switch的case写的是null,那么在编译时无法求出hashCode,因此在编译时就会报错了。
switch支持String只是一个语法糖,由javac来负责生成相应的代码。底层的JVM在switch上并没有进行修改。
参考 http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
类别:Java
在Java7之前,switch只能支持 byte、short、char、int或者其对应的封装类以及Enum类型。在Java7中,呼吁很久的String支持也终于被加上了。
例如,下面是一段switch中使用String的示例代码。
在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了吧。
如果switch传入的null,那么在运行时对一个null对象调用hashCode方法会出现NullPointerException。
如果switch的case写的是null,那么在编译时无法求出hashCode,因此在编译时就会报错了。
switch支持String只是一个语法糖,由javac来负责生成相应的代码。底层的JVM在switch上并没有进行修改。
参考 http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
类别:Java
例如,下面是一段switch中使用String的示例代码。
01 | public class Test { |
02 |
03 | public void test(String str) { |
04 | switch (str) { |
05 | case "abc" : |
06 | System.out.println( "abc" ); |
07 | break ; |
08 | case "def" : |
09 | System.out.println( "def" ); |
10 | break ; |
11 | default : |
12 | System.out.println( "default" ); |
13 | } |
14 | } |
15 |
16 | } |
需要注意的是,传给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了吧。
01 | public class Test { |
02 | public void test(String str) { |
03 | int i = - 1 ; |
04 | switch (str.hashCode()) { |
05 | case 96354 : // "abc".hashCode() |
06 | if (str.equals( "abc" )) { |
07 | i = 0 ; |
08 | } |
09 | break ; |
10 | case 99333 : // "def".hashCode() |
11 | if (str.equals( "def" )) { |
12 | i = 1 ; |
13 | } |
14 | break ; |
15 | default : |
16 | break ; |
17 | } |
18 |
19 | switch (i) { |
20 | case 0 : |
21 | System.out.println( "abc" ); |
22 | break ; |
23 | case 1 : |
24 | System.out.println( "def" ); |
25 | break ; |
26 | default : |
27 | System.out.println( "default" ); |
28 | } |
29 | } |
30 | } |
如果switch的case写的是null,那么在编译时无法求出hashCode,因此在编译时就会报错了。
switch支持String只是一个语法糖,由javac来负责生成相应的代码。底层的JVM在switch上并没有进行修改。
参考 http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
类别:Java
在Java7之前,switch只能支持 byte、short、char、int或者其对应的封装类以及Enum类型。在Java7中,呼吁很久的String支持也终于被加上了。
例如,下面是一段switch中使用String的示例代码。
01 | public class Test { |
02 |
03 | public void test(String str) { |
04 | switch (str) { |
05 | case "abc" : |
06 | System.out.println( "abc" ); |
07 | break ; |
08 | case "def" : |
09 | System.out.println( "def" ); |
10 | break ; |
11 | default : |
12 | System.out.println( "default" ); |
13 | } |
14 | } |
15 |
16 | } |
需要注意的是,传给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了吧。
01 | public class Test { |
02 | public void test(String str) { |
03 | int i = - 1 ; |
04 | switch (str.hashCode()) { |
05 | case 96354 : // "abc".hashCode() |
06 | if (str.equals( "abc" )) { |
07 | i = 0 ; |
08 | } |
09 | break ; |
10 | case 99333 : // "def".hashCode() |
11 | if (str.equals( "def" )) { |
12 | i = 1 ; |
13 | } |
14 | break ; |
15 | default : |
16 | break ; |
17 | } |
18 |
19 | switch (i) { |
20 | case 0 : |
21 | System.out.println( "abc" ); |
22 | break ; |
23 | case 1 : |
24 | System.out.println( "def" ); |
25 | break ; |
26 | default : |
27 | System.out.println( "default" ); |
28 | } |
29 | } |
30 | } |
如果switch的case写的是null,那么在编译时无法求出hashCode,因此在编译时就会报错了。
switch支持String只是一个语法糖,由javac来负责生成相应的代码。底层的JVM在switch上并没有进行修改。
参考 http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html
类别:Java
相关文章推荐
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch支持String的实现细节
- Java7中的switch...case支持string的实现细节
- Java7中的switch支持String的实现细节
- Java jre7及以上版本中的switch支持String的实现细节
- Java7中switch支持String
- Java 7 switch支持String类型的原理和关于switch一些细节
- java7新特性 java7switch支持String
- Java7中Switch支持String
- Java7中Switch语句支持String
- Java 7新特性: switch中对String的支持