条件表达式中Java中的错误行为

时间:2011-06-28 12:55:29

标签: java language-design conditional-operator autoboxing

一个简单的表达方式:

Object val = true ? 1l : 0.5;

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

它不需要任何自动装箱作为

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

结果具有相同的行为。

只是为了澄清:

Object val = true ? "1" : 0.5;

会产生正确的字符串

有人可以解释我为什么这样定义吗?对我而言,设计似乎相当糟糕或实际上是一个错误。

5 个答案:

答案 0 :(得分:7)

Java语言规范Section 15.25(粗体相关部分)中描述了这一点:

  

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

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

  2.   
  3. 如果第二个和第三个操作数之一的类型为boolean [...]

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

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

         
        
    1. 如果其中一个操作数的类型为byte [...]

    2.   
    3. 如果其中一个操作数是T类型,其中T是byte,short或char,[...]

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

    6. 类型   
    7. 如果其中一个操作数的类型为Short [...]

    8.   
    9. 如果其中一个操作数是类型;字符[...]

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

    12.   
  8.   
  9. 否则,第二个和第三个操作数分别为S1和S2类型。设T1是应用到S1的装箱转换所产生的类型,让T2为应用装箱转换到S2的结果。条件表达式的类型是应用捕获转换的结果(第5.1节。 10)至 lub(T1,T2)(§15.12.2.7)。

  10.   

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


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

但是,您可以通过执行

强制它使用规则5
Object val = false ? (Number) 1L : .5;

答案 1 :(得分:4)

因为表达式必须是一种类型。

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

在你的情况下,编译器看到了什么?并使用相同的规则将表达式的结果赋值为double(您可以将long写为double,但不能将所有双精度写为long)。

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

写作时

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

你需要考虑

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

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

答案 4 :(得分:0)

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

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