Java 条件表达式中的错误行为
一个简单的表达式:
Object val = true ? 1l : 0.5;
val是什么类型?那么,从逻辑上讲,val 应该是一个值为 1 的 Long 对象。但 Java 认为 val 是一个 Double,其值为 1.0。
它不必对自动装箱进行任何操作,因为
Object val = true ? new Long(1) : new Double(0.5);
结果具有相同的行为。
只是为了澄清:
Object val = true ? "1" : 0.5;
产生正确的字符串。
谁能解释一下为什么他们这样定义?对我来说,它的设计似乎相当糟糕,或者实际上是一个错误。
A simple expression:
Object val = true ? 1l : 0.5;
What type is val? Well, logically, val should be a Long object with value 1. But Java thinks that val is a Double with value 1.0.
It doesn't have to to anything with autoboxing as
Object val = true ? new Long(1) : new Double(0.5);
results with same behavior.
Just to clarify:
Object val = true ? "1" : 0.5;
results in the correct String.
Can anybody explain me why they have defined this like that? For me it seems to be rather really bad designed or actually a bug.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Java 语言规范第 15.25 节对此进行了描述(相关部分以粗体显示):
上一段中提到的“lub”代表最小上限,指的是 T1 和 T2 常见的最具体的超类型。
至于
Object val = true 的情况? 1l : 0.5;
我同意如果应用规则 5(在盒装值上)会更精确。我想当考虑到自动装箱时,规则会变得模糊(甚至更加复杂)。例如,表达式b 是什么类型? new Byte(0) : 0.5
有吗?但是,您可以通过执行以下操作强制它使用规则 5
This is described in the Java Language Specification Section 15.25 (relevant parts in bold face):
The "lub" mentioned in the last paragraph stands for least upper bound and refers to the most specific super type common for T1 and T2.
As for the case with
Object val = true ? 1l : 0.5;
I agree that it would be more precise if it applied rule 5 (on the boxed values). I guess the rules would become ambiguous (or even more complicated) when taking autoboxing into account. What type would for instance the expressionb ? new Byte(0) : 0.5
have?You can however force it to use rule 5 by doing
因为表达式需要是一种类型。
如果执行 1l + 0.5d,则会以 1.5d 结束,因为编译器会自动将类型更改为可以允许所有可能结果的类型。
在你的情况下,编译器会看到 ?并使用相同的规则将表达式的结果分配给 double(您可以将 long 写为 double,但不能将所有 double 写为 long)。
Because the expression needs to be of a type.
If you do 1l + 0.5d, you end with 1.5d because the compiler changes automatically the types to the one which can allow all possible results.
In your case, the compiler sees ? and assigns the result of the expression the double using the same rule (you can write a long as a double, but not all doubles as longs).
这不是设计缺陷:
编译器必须确定整个表达式的类型
true ? 1l:0.5
。它尝试使用需要尽可能少转换的类型。由于 0.5 不适合
long
(不损失精度),因此表达式的结果不能太长 - 因此,它必须是double
并且 long简单地转换(不损失精度)。请注意,您不能有条件地使表达式具有不同类型 - 无论条件如何,第三级表达式都必须计算为相同类型。
在第二个片段中,Object 是唯一兼容的类型 - Double 被装箱,而 String 可以简单地分配。
That's not a design flaw:
The compiler has to determine the type of the entire expression
true ? 1l : 0.5
. It tries using a type where as few conversions as possible are required.As 0.5 does not fit into a
long
(without loss of precision), the result of the expression can't be long - therefore, it has to bedouble
and the long is simply converted (no loss of precision).Note that you can't have an expression conditionally having different types - a tertiary expression has to evaulate to the same type regardless of the condition.
In the second snippet, Object is the only compatible type - the Double gets boxed and the String can be simply assigned.
当您编写时,
您需要考虑
需要有一个值...编译器需要提出一个涵盖两种可能值的类型。对于您的示例,它是双倍的。
When you write
you need to consider that
needs to have a value... The compiler needs to come up with a type that covers both possible values. For your example, it was double.
我无法为您提供充分的理由,但表达式的类型是由 Java 语言规范给出的:http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.25
在 JLS 中,所有数字类型都会被处理作为特殊情况。
I cannot provide you with a good reason, but the type of the expression is given by the Java Language Specification: http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.25
In the JLS all the numeric types are treated as special cases.