一个简单的表达方式:
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;
会产生正确的字符串。
有人可以解释我为什么这样定义吗?对我而言,设计似乎相当糟糕或实际上是一个错误。
答案 0 :(得分:7)
Java语言规范Section 15.25(粗体相关部分)中描述了这一点:
条件表达式的类型确定如下:
如果第二个和第三个操作数具有相同的类型[...]
如果第二个和第三个操作数之一的类型为boolean [...]
如果第二个和第三个操作数之一是null类型[...]
否则,如果第二个和第三个操作数的类型可转换(第5.1.8节)为数字类型,则有几种情况:
如果其中一个操作数的类型为byte [...]
如果其中一个操作数是T类型,其中T是byte,short或char,[...]
- 类型
如果其中一个操作数是Byte [...]
如果其中一个操作数的类型为Short [...]
如果其中一个操作数是类型;字符[...]
否则,对操作数类型应用二进制数字提升(第5.6.2节),条件表达式的类型是第二个和第三个操作数的提升类型。 请注意,二进制数字促销会执行拆箱转换(第5.1.8节)和值集转换(第5.1.13节)。
- 醇>
否则,第二个和第三个操作数分别为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
会有什么类型?
但是,您可以通过执行
强制它使用规则5Object 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中,所有数字类型都被视为特殊情况。