Integer i = ...
    
switch (i) {
    case null:
        doSomething0();
        break;    
}

在上面的代码中,我不能在switch case语句中使用null。我该怎么做呢?我不能用默认,因为我想做别的。


当前回答

Java文档明确指出:

禁止使用null作为开关标签可以防止编写永远不能执行的代码。如果开关表达式是引用类型,例如盒装基元类型或enum,如果表达式在运行时求值为空,则会发生运行时错误。

在switch语句执行之前,必须验证是否为空。

if (i == null)

参见Switch语句

case null: // will never be executed, therefore disallowed.

其他回答

你不能。你可以在switch中使用基本类型(int, char, short, byte)和String(仅在java 7中使用字符串)。原语不能为空。 开关前检查i是否处于单独状态。

switch(i)如果i为null,将抛出NullPointerException,因为它将尝试将Integer拆箱为int。所以case null,恰好是非法的,永远不会被达到。

你需要在switch语句之前检查i是否为空。

你也可以使用String.valueOf((对象)nullableString) 就像

switch (String.valueOf((Object) nullableString)) {
case "someCase"
    //...
    break;
...
case "null": // or default:
    //...
        break;
}

参见有趣的SO Q/A:为什么String.valueOf(null)抛出NullPointerException

switch (String.valueOf(value)){
    case "null":
    default: 
}

这在Java 18之前是不可能用switch语句实现的。在切换之前必须检查是否为空。但是现在,有了模式匹配,这些都成为过去式了。看看JEP 420:

模式匹配和空 传统上,switch语句和表达式会抛出 如果选择器表达式的结果为null,则为NullPointerException null测试必须在开关外部完成:

static void testFooBar(String s) {
     if (s == null) {
         System.out.println("oops!");
         return;
     }
     switch (s) {
         case "Foo", "Bar" -> System.out.println("Great");
         default           -> System.out.println("Ok");
     }
 }

当switch只支持少数参考类型时,这是合理的。 然而,if switch允许任何类型的选择器表达式和大小写 标签可以有类型模式,这样独立的空测试才有感觉 就像一个武断的区分,并引起不必要的样板文件和 犯错的机会。最好是集成空测试 进入开关:

static void testFooBar(String s) {
    switch (s) {
        case null         -> System.out.println("Oops");
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");   
  }
}

更多关于开关(包括空变量的例子)在Oracle Docs - switch