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

在上面的代码中,我不能在 switch case 语句中使用 null。我怎样才能做到这一点?我不能使用default,因为那时我想做其他事情。

4

13 回答 13

334

switch这对于 Java 中的语句是不可能的。null之前检查switch

if (i == null) {
    doSomething0();
} else {
    switch (i) {
    case 1:
        // ...
        break;
    }
}

您不能在switch语句*中使用任意对象。编译器不抱怨switch (i)where iis anInteger的原因是 Java 自动拆箱Integerint. 正如 assylias 已经说过的,拆箱会抛出NullPointerExceptionwhen iis null

*从 Java 7 开始,您可以使用Stringinswitch语句。

Oracle Docs - Switch中有关switch(包括带有空变量的示例)的更多信息

于 2012-04-26T11:07:11.290 回答
125
switch ((i != null) ? i : DEFAULT_VALUE) {
        //...
}
于 2015-06-02T16:04:20.823 回答
45

switch(i)如果 i 是null,将抛出 NullPointerException ,因为它会尝试将其拆箱Integerint. 所以case null,这恰好是非法的,无论如何都不会达到。

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

于 2012-04-26T11:06:20.543 回答
25

Java docs clearly stated that:

The prohibition against using null as a switch label prevents one from writing code that can never be executed. If the switch expression is of a reference type, such as a boxed primitive type or an enum, a run-time error will occur if the expression evaluates to null at run-time.

You must have to verify for null before Swithch statement execution.

if (i == null)

See The Switch Statement

case null: // will never be executed, therefore disallowed.
于 2012-04-26T11:14:48.647 回答
15

鉴于:

public enum PersonType {
    COOL_GUY(1),
    JERK(2);

    private final int typeId;
    private PersonType(int typeId) {
        this.typeId = typeId;
    }

    public final int getTypeId() {
        return typeId;
    }

    public static PersonType findByTypeId(int typeId) {
        for (PersonType type : values()) {
            if (type.typeId == typeId) {
                return type;
            }
        }
        return null;
    }
}

对我来说,这通常与数据库中的查找表一致(仅适用于很少更新的表)。

但是,当我尝试findByTypeId在 switch 语句中使用时(很可能来自用户输入)......

int userInput = 3;
PersonType personType = PersonType.findByTypeId(userInput);
switch(personType) {
case COOL_GUY:
    // Do things only a cool guy would do.
    break;
case JERK:
    // Push back. Don't enable him.
    break;
default:
    // I don't know or care what to do with this mess.
}

...正如其他人所说,这会导致 NPE @ switch(personType) {。我开始实施的一种解决方法(即“解决方案”)是添加一个UNKNOWN(-1)类型。

public enum PersonType {
    UNKNOWN(-1),
    COOL_GUY(1),
    JERK(2);
    ...
    public static PersonType findByTypeId(int id) {
        ...
        return UNKNOWN;
    }
}

现在,您不必在重要的地方进行空值检查,您可以选择或不处理UNKNOWN类型。(注意:-1在业务场景中不太可能是标识符,但显然选择对您的用例有意义的东西)。

于 2015-10-02T21:48:45.973 回答
5

你必须做一个

if (i == null) {
   doSomething0();
} else {
   switch (i) {
   }
}
于 2012-04-26T11:07:02.430 回答
4

一些库试图提供内置 javaswitch语句的替代方案。Vavr就是其中之一,他们将其推广到模式匹配。

这是他们文档中的一个示例:

String s = Match(i).of(
    Case($(1), "one"),
    Case($(2), "two"),
    Case($(), "?")
);

您可以使用任何谓词,但它们提供了许多开箱即用的谓词,并且$(null)完全合法。我发现这是一个比替代方案更优雅的解决方案,但这需要 java8 和对 vavr 库的依赖...

于 2016-05-26T12:13:12.767 回答
3

你也可以使用String.valueOf((Object) nullableString) 喜欢

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

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

于 2018-05-06T12:00:24.823 回答
3

基于@tetsuo 的回答,使用 java 8 :

Integer i = ...

switch (Optional.ofNullable(i).orElse(DEFAULT_VALUE)) {
    case DEFAULT_VALUE:
        doDefault();
        break;    
}
于 2019-12-10T09:59:39.717 回答
3
switch (String.valueOf(value)){
    case "null":
    default: 
}
于 2017-11-30T10:58:12.407 回答
2

你不能。您可以在 switch 中使用原语(int、char、short、byte)和字符串(仅限 java 7 中的字符串)。原语不能为空。切换前
检查单独的条件。i

于 2012-04-26T11:06:03.323 回答
1

我今天刚刚了解到,您不必仅仅因为 if 正在检查 null 就添加另一层缩进/大括号。您可以执行以下任一操作:

if (i == null) {
    // ...
} else switch (i) {
    case 1:
        // ...
        break;
    default:
        // ...
}

或者

if (i != null) switch (i) {
    case 1:
        // ...
        break;
    default:
        // ...
} else {
    // ...
}
于 2021-05-18T04:35:23.753 回答
0

只需考虑 SWITCH 的工作方式,

  • 在原语的情况下,我们知道它可能会因 NPE 自动装箱而失败
  • 但是对于Stringenum,它可能正在调用 equals 方法,这显然需要一个 LHS 值,在该值上调用 equals 。因此,鉴于不能对 null 调用任何方法,switch无法处理 null。
于 2019-06-18T10:24:57.217 回答