为什么String switch语句不支持null case?

问题

我只是想知道为什么Java 7switch语句不支持anullcase而是throwsNullPointerException?请参阅下面的注释行(示例摘自Java Tutorials文章switch):

{
    String month = null;
    switch (month) {
        case "january":
            monthNumber = 1;
            break;
        case "february":
            monthNumber = 2;
            break;
        case "march":
            monthNumber = 3;
            break;
        //case null:
        default: 
            monthNumber = 0;
            break;
    }

    return monthNumber;
}

这样可以避免在每个switchuse之前进行空检查的if条件。


#1 热门回答(130 赞)

正如damryfbfnetsipoints out中的评论,JLS §14.11有以下注释:

禁止使用null作为开关标签可以防止编写永远不会执行的代码。如果switch表达式是引用类型,即String或盒装基元类型或枚举类型,那么如果表达式在运行时求值为null,则会发生运行时错误。在Java编程语言的设计者的判断中,这比默认跳过整个switch语句或选择在默认标签(如果有)之后执行语句(如果有的话)更好。

(强调我的)

虽然最后一句话略过了使用case null:的可能性,但这似乎是合理的,并提供了语言设计者的意图。

如果我们更倾向于查看实现细节,那么this blog post作者Christian Hujer对于为什么不允许在交换机中使用null有一些深刻的猜测(尽管它以enum开关而不是String开关为中心):

在引擎盖下,switch语句通常会编译为tablesswitch字节代码。转换的"物理"参数及其案例都是整数。要打开的int值是通过调用方法Enum.ordinal()来确定的。 [...]序数从零开始。这意味着,将null映射到0不是一个好主意。第一个枚举值的开关将与null无法区分。也许以1开始计算枚举的序数是个好主意。然而,它没有被定义为这样,并且这个定义不能改变。

Stringswitchesare implemented differently中,enumswitch排在第一位,并为引用类型36656103时引用类型的开启行为设置了先例。


#2 热门回答(23 赞)

它不漂亮,但是String.valueOf()允许你在交换机中使用空字符串。如果找到null,则将其转换为488281515,否则它只返回你传递的相同String。如果你没有明确地处理"null",那么它将转到default。唯一需要注意的是,没有办法区分String"null"和一个实际的null变量。

String month = null;
    switch (String.valueOf(month)) {
        case "january":
            monthNumber = 1;
            break;
        case "february":
            monthNumber = 2;
            break;
        case "march":
            monthNumber = 3;
            break;
        case "null":
            monthNumber = -1;
            break;
        default: 
            monthNumber = 0;
            break;
    }
    return monthNumber;

#3 热门回答(22 赞)

一般null令人讨厌处理;也许更好的语言可以没有null

你的问题可能会被解决

switch(month==null?"":month)
    {
        ...
        //case "":
        default: 
            monthNumber = 0;

    }