【问题标题】:Wrong type in Java conditional assignmentJava条件赋值中的错误类型
【发布时间】:2013-11-12 19:41:47
【问题描述】:

在下面的代码中,我有两个相同的条件赋值操作,一个返回 Double 类型的对象,第二个返回字符串“Integer”。

double d = 24.0;

Number o = (d % 1 == 0) ? new Double(d).intValue() : new Double(d).doubleValue();
String result = (d % 1 == 0) ? "Integer" : "Double";

System.out.println(o.getClass()); // prints "class java.lang.Double"
System.out.println(result); // Integer

为什么完全相同的表达式会返回两个不同的东西?

【问题讨论】:

  • @RichardTingle 在这里我们都认为?: 的行为与 if 语句相同
  • 我几乎认为这是一个简单 if 语句的更紧凑的版本!
  • if 语句和三元运算符?: 是不同的野兽。前者是一个陈述,因此没有价值;后者是一个表达式,因此有一个值,并且该值需要一个类型——选择的类型基本上是适用于三元的两个“分支”的最具体的类型。
  • 看懂了就说得通了,但我看得出来是多么容易被它烫到

标签: java conditional-operator


【解决方案1】:

嗯,那是因为JLS specs for the conditional operator:

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

  • ...
  • 否则,二进制数字提升 (§5.6.2) 将应用于操作数类型,并且 条件表达式的类型是第二个的提升类型 和第三个操作数。

数字提升在§5.6.2 中定义。它说:

加宽原语转换(第 5.1.2 节)用于转换或 两个操作数均由以下规则指定:

  • 如果任一操作数为 double 类型,则将另一个转换为 double。
  • ...

【讨论】:

  • 感谢 Martijn,非常好的收获。
  • @SamuelO'Malley - 您可以通过将三元运算的两个结果都转换为Number 来“修复”它以获得预期的输出,这将消除编译器进行数字提升的需要: Number o = (d % 1 == 0) ? (Number)new Double(d).intValue() : (Number)new Double(d).doubleValue();
  • 是条件运算符。它恰好是目前唯一的三元运算符,但这不是它的名字。这就是为什么您获得的链接是“条件运算符?:”而不是“三元运算符?:”
  • @MartijnCourteaux:是的——它相当于“一元”和“二元”,但只有三个。这是我的一个小烦恼,我渴望 Java 和 C# 引入另一个三元运算符,只是为了使之前关于“三元运算符”的所有陈述都模棱两可:)
  • @yshavit:但是使用运算符的name不是更有用吗?最重要的是它真的只有三个操作数吗?我的反对部分是因为人们相信“三元运算符”真的是它的名字,而实际上它不是。
【解决方案2】:

嗯 0.0 仍然 == 到 0

System.out.println(0 == 0.0); // equals true

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.25

【讨论】:

  • 这个问题与 Boxed primative 的类型有关,而不是 value
  • 然而,Double.valueOf(0).equals(Integer.valueOf(0))false -- 这更接近 OP 的情况。
  • 变量的类型对价值行为很重要。例如 2/4==0,而 2.0/4.0==0.5。因此,这不是纯粹的学术
  • 另外,请注意 0 == 0.0 仅是正确的,因为左侧被提升为双精度(值 0.0)。如果您尝试执行类似 int i = true ? 0 : 0.0 的操作,那么您'会得到一个编译时错误,因为true ? 0 : 0.0 的类型是double,如果没有显式转换,就不能将其分配给int
猜你喜欢
  • 2018-07-04
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
相关资源
最近更新 更多