2

一个简单的表达:

Object val = true ? 1l : 0.5;

val是什么类型?好吧,从逻辑上讲,val应该是一个Long值为1的对象。但是 Java 认为val是一个Double,其值为1.0

自动装箱不需要任何东西

Object val = true ? new Long(1) : new Double(0.5);

结果具有相同的行为。

只是为了澄清:

Object val = true ? "1" : 0.5;

产生正确的String

谁能解释我为什么他们这样定义?对我来说,这似乎是一个非常糟糕的设计或实际上是一个错误。

4

5 回答 5

7

这在 Java 语言规范第 15.25 节中进行了描述(相关部分以粗体显示):

条件表达式的类型确定如下:

  1. 如果第二个和第三个操作数具有相同的类型 [...]

  2. 如果第二个和第三个操作数之一是布尔类型 [...]

  3. 如果第二个和第三个操作数之一是 null 类型 [...]

  4. 否则,如果第二个和第三个操作数具有可转换(第 5.1.8 节)为数字类型的类型,则有以下几种情况:

    1. 如果其中一个操作数是字节类型 [...]

    2. 如果其中一个操作数是 T 类型,其中 T 是字节、短或字符,则 [...]

    3. 如果其中一个操作数是 Byte [...]

    4. 如果其中一个操作数是 Short [...]

    5. 如果其中一个操作数是类型;特点 [...]

    6. 否则,二进制数值提升(第 5.6.2 节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。请注意,二进制数字提升执行拆箱转换(第 5.1.8 节)和值集转换(第 5.1.13 节)。

  5. 否则,第二个和第三个操作数分别是 S1 和 S2 类型。令 T1 为对 S1 应用装箱转换产生的类型,令 T2 为对 S2 应用装箱转换产生的类型。条件表达式的类型是将捕获转换 (§5.1.10) 应用于lub(T1, T2) (§15.12.2.7) 的结果。

上一段中提到的“lub”代表最小上限,指的是 T1 和 T2 最常见的超类型。


至于Object val = true ? 1l : 0.5;我同意的情况,如果它应用规则 5(在盒装值上)会更精确。我猜在考虑自动装箱时规则会变得模棱两可(甚至更复杂)。例如,表达式b ? new Byte(0) : 0.5有什么类型?

但是,您可以通过执行强制它使用规则 5

Object val = false ? (Number) 1L : .5;
于 2011-06-28T13:00:12.297 回答
4

因为表达式需要是一个类型。

如果执行 1l + 0.5d,则以 1.5d 结束,因为编译器会自动将类型更改为可以允许所有可能结果的类型。

在您的情况下,编译器会看到 ? 并使用相同的规则将表达式的结果分配给 double(您可以将 long 写为 double,但并非所有 double 都写为 long)。

于 2011-06-28T13:01:18.017 回答
1

这不是设计缺陷:
编译器必须确定整个表达式的类型true ? 1l : 0.5。它尝试使用需要尽可能少的转换的类型。
由于 0.5 不适合 a long(不损失精度),因此表达式的结果不能很长 - 因此,它必须是double并且 long 被简单地转换(不损失精度)。

请注意,您不能有条件地具有不同类型的表达式 - 无论条件如何,三级表达式都必须评估为相同的类型

在第二个片段中,Object 是唯一兼容的类型 - Double 被装箱并且可以简单地分配 String。

于 2011-06-28T13:00:35.133 回答
1

当你写

Object val = true ? new Long(1) : new Double(0.5);

你需要考虑到

(new Long(1) : new Double(0.5))

需要有一个值......编译器需要提出一个涵盖两个可能值的类型。对于您的示例,它是双倍的。

于 2011-06-28T13:03:58.177 回答
0

我无法为您提供充分的理由,但表达式的类型由 Java 语言规范给出:http: //java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.25

在 JLS 中,所有数字类型都被视为特殊情况。

于 2011-06-28T13:01:36.900 回答