为什么Java 12会尝试将交换机的结果转换为数字?

问题描述 投票:42回答:1

我同意这段代码:

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

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

java switch-statement java-12
1个回答
47
投票

根据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;
};

在我的shell中,这失败了:

|  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;
|                ^--^

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

它应该足以看到如何确定独立类型(rules here):

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

  • 如果结果表达式都具有相同的类型(可能是null类型),那么这就是switch表达式的类型。
  • 否则,如果每个结果表达式的类型是布尔值或布尔值,则对每个类型为Boolean的结果表达式应用拆箱转换(5.1.8),并且switch表达式的类型为boolean。
  • 否则,如果每个结果表达式的类型可转换为数字类型(5.1.8),则switch表达式的类型是应用于结果表达式的数字提升(5.6)的结果。
  • 否则,装箱转换(5.1.7)将应用于具有基本类型的每个结果表达式,之后切换表达式的类型是将捕获转换(5.1.10)应用于最小上限的结果(4.10.4 )结果表达式的类型。

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

至于为什么float是结果的类型,请参阅Numeric Contexts部分。

© www.soinside.com 2019 - 2024. All rights reserved.