使用枚举定义常量时,会伴有大量的switch语句判断,目的是伪类每个枚举项解释其行为,例如:
1 public class Client { 2 public static void main(String[] args) { 3 4 doSports(null); 5 } 6 7 public static void doSports(Season season) { 8 switch (season) { 9 case Spring: 10 System.out.println("春天放风筝"); 11 break; 12 case Summer: 13 System.out.println("夏天游泳"); 14 break; 15 case Autumn: 16 System.out.println("秋天捉知了"); 17 break; 18 case Winter: 19 System.out.println("冬天滑冰"); 20 break; 21 default: 22 System.out.println("输入错误!"); 23 break; 24 } 25 } 26 } 27 28 enum Season { 29 Spring, Summer, Autumn, Winter; 30 }
上面的代码输入 了一个Season类型的枚举,然后使用switch进行匹配,目的是输出每个季节的活动.但是代码是否有问题?
doSports(null),似乎会打印出"输出错误",因为在switch中没有匹配到指定的值,所以会打印出default的代码块.
运行看结果:
Exception in thread "main" java.lang.NullPointerException at cn.summerchill.test.Client.doSports(Client.java:12) at cn.summerchill.test.Client.main(Client.java:8)
switch那一行报出了空指针...这就是枚举和switch的特性有关了...此问题也是在开发中经常发生.
目前Java中的switch语句只能判断byte,short,char,int类型(JDK7中已经允许使用String类型),这是Java编译器的限制,问题是为什么枚举类型也可以 跟在switch后面呢?
因为编译时,编译器判断出switch语句后面的参数是枚举类型,然后就根据枚举的排序值继续匹配,也就是说上面代码与以下代码相同:
public class Client { public static void main(String[] args) { doSports(Season.Spring); } public static void doSports(Season season) { switch (season.ordinal()) { case Season.Spring.ordinal(): System.out.println("春天放风筝"); break; case Season.Summer.ordinal(): System.out.println("夏天游泳"); break; case Season.Autumn.ordinal(): System.out.println("秋天捉知了"); break; case Season.Winter.ordinal(): System.out.println("冬天滑冰"); break; default: System.out.println("输入错误!"); break; } } } enum Season { Spring, Summer, Autumn, Winter; }
但是这样会报错的...在各个case语句上 报 case expressions must be constant expressions..但是书中却没有提到这一点....不知道为什么.....
switch语句是先计算season变量的排序值,然后与枚举常量的每个排序值进行对比.
在我们的例子中season的变量值是null,无法执行ordinal()方法,于是报空指针异常了.
解决方法也有很简单:在doSports()方法中判断输入的参数是否是null即可.
ordinal 单词是序数的意思. ordinal()方法获得的是从0开始的数字 .....Spring对应为0 ,Summer为1,Autumn为2,Winter为3