47

我同意这段代码:

var y = switch (0) {
    case 0 -> '0';
    case 1 -> 0.0F;
    case 2 -> 2L;
    case 3 -> true;
    default -> 4;
};
System.out.println(y);
System.out.println(((Object) y).getClass().getName());

返回这个:

0
java.lang.Character

但是如果你删除布尔值:

var y = switch (0) {
    case 0 -> '0';
    case 1 -> 0.0F;
    case 2 -> 2L;
    default -> 4;
};
System.out.println(y);
System.out.println(((Object) y).getClass().getName());

返回这个:

48.0
java.lang.Float

我想这个结果是出乎意料的。

4

1 回答 1

51

根据 switch 表达式的JEP,一个 switch 表达式是一个 poly 表达式:

switch 表达式是一个 poly 表达式;如果目标类型已知,则将这种类型向下推入每个手臂。switch 表达式的类型是它的目标类型,如果已知的话;如果不是,则通过组合每个案例臂的类型来计算独立类型。

因为您没有目标类型,所以不会检查表达式以匹配任何给定类型,这是预期的。

您可以通过替换var为以下类型来验证这一点:

int y = switch (0) {
    case 0 -> '0';
    case 1 -> 0.0F;
    case 2 -> 2L;
    case 3 -> true;
    default -> 4;
};

在我的外壳中,这失败了:

|  Error:
|  incompatible types: bad type in switch expression
|      possible lossy conversion from float to int
|      case 1 -> 0.0F;
|                ^--^
|  Error:
|  incompatible types: bad type in switch expression
|      possible lossy conversion from long to int
|      case 2 -> 2L;
|                ^^
|  Error:
|  incompatible types: bad type in switch expression
|      boolean cannot be converted to int
|      case 3 -> true;
|                ^--^

但是,如果您删除布尔值:...

看看如何确定独立类型就足够了(这里的规则):

独立开关表达式的类型确定如下

  • 如果结果表达式都具有相同的类型(可能是 null 类型),那么这就是 switch 表达式的类型。

  • 否则,如果每个结果表达式的类型是 boolean 或 Boolean,则对每个 Boolean 类型的结果表达式应用拆箱转换 (5.1.8),并且 switch 表达式具有 boolean 类型。

  • 否则,如果每个结果表达式的类型都可以转换为数字类型 (5.1.8),则 switch 表达式的类型是应用于结果表达式的数字提升 (5.6) 的结果。

  • 否则,将装箱转换 (5.1.7) 应用于每个具有原始类型的结果表达式,之后 switch 表达式的类型是将捕获转换 (5.1.10) 应用于最小上限 (4.10.4) 的结果) 的结果表达式的类型。

据我所知,当您删除布尔表达式时,您会留下数字表达式(char '0'( int 48) 被提升为float 48.0)。请参阅上面的第三个要点。

至于为什么float是结果的类型,请参见数值上下文部分。

于 2019-03-22T08:07:42.290 回答