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

发布于 2024-11-17 15:43:51 字数 550 浏览 2 评论 0原文

一个简单的表达式:

Object val = true ? 1l : 0.5;

val是什么类型?那么,从逻辑上讲,val 应该是一个值为 1Long 对象。但 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

少女的英雄梦 2024-11-24 15:43:51

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

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

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

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

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

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

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

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

This is described in the Java Language Specification Section 15.25 (relevant parts in bold face):

The type of a conditional expression is determined as follows:

  1. If the second and third operands have the same type [...]

  2. If one of the second and third operands is of type boolean [...]

  3. If one of the second and third operands is of the null type [...]

  4. Otherwise, if the second and third operands have types that are convertible (§5.1.8) to numeric types, then there are several cases:

    1. If one of the operands is of type byte [...]

    2. If one of the operands is of type T where T is byte, short, or char, [...]

    3. If one of the operands is of type Byte [...]

    4. If one of the operands is of type Short [...]

    5. If one of the operands is of type; Character [...]

    6. Otherwise, binary numeric promotion (§5.6.2) is applied to the operand types, and the type of the conditional expression is the promoted type of the second and third operands. Note that binary numeric promotion performs unboxing conversion (§5.1.8) and value set conversion (§5.1.13).

  5. Otherwise, the second and third operands are of types S1 and S2 respectively. Let T1 be the type that results from applying boxing conversion to S1, and let T2 be the type that results from applying boxing conversion to S2. The type of the conditional expression is the result of applying capture conversion (§5.1.10) to lub(T1, T2) (§15.12.2.7).

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 expression b ? new Byte(0) : 0.5 have?

You can however force it to use rule 5 by doing

Object val = false ? (Number) 1L : .5;
红颜悴 2024-11-24 15:43:51

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

如果执行 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).

逆流 2024-11-24 15:43:51

这不是设计缺陷:
编译器必须确定整个表达式的类型 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 be double 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.

红ご颜醉 2024-11-24 15:43:51

当您编写时,

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

您需要考虑

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

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

When you write

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

you need to consider that

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

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.

絕版丫頭 2024-11-24 15:43:51

我无法为您提供充分的理由,但表达式的类型是由 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文