object Test {
def main(args: Array[String]): Unit = {
val x = 123456789L
val y = 1.0F
val a = x - (if (true) { x } else { y })
val b = (if (true) { x } else { y }) - x
}
}
运行此代码,a为-3.0: Float
,b为0.0: Float
。 (由于精度损失,x.toFloat
为1.23456792E8: Float
。)
根据Conditional Expressions和Weak Conformance:在两种情况下,if
表达式的类型均为Float
。 ({Float
是Long
(那么部分的类型)和Float
(其他部分的类型)的最小最小上限。
结果,在第一种情况下,我们有Long - Float
,在第二种情况下,我们有Float - Long
。
在第一种情况下,两个操作数都被加宽(?)到Double
以进行计算,结果被缩小到Float
以进行赋值。在第二种情况下,两个操作数都仅扩展为Float
。
根据Numeric Widening,a
的预期类型必须为Double
,两个操作数才能扩展为Double
。但是,它是Float
。
这是怎么回事?这里还有其他规则吗?这是编译器中的错误吗?请详细解释并引用支持证据。谢谢。
可以通过查看生成的字节码来确认观察到的行为:
$ javap -c 'Test$.class'
Compiled from "Test.sc"
public final class Test$ {
public static final Test$ MODULE$;
public static {};
Code:
0: new #2 // class Test$
3: invokespecial #12 // Method "<init>":()V
6: return
public void main(java.lang.String[]);
Code:
0: ldc2_w #15 // long 123456789l
3: lstore_2
4: fconst_1
5: fstore 4
7: lload_2
8: l2d
9: lload_2
10: l2f
11: f2d
12: dsub
13: d2f
14: fstore 5
16: lload_2
17: l2f
18: lload_2
19: l2f
20: fsub
21: fstore 6
23: return
}
对比度:
l2d
,后一种情况是l2f
和f2d
;和第二种情况下的l2f
dsub
,后一种情况是d2f
;和第二种情况下的fsub