Why does *= not give any errors when implicitly casting a float to an int?
我之前遇到过一种情况,我尝试了以下两个代码位:
1 2 | int score = 100; score = score * 1.05; |
和
1 2 | int score = 100; score *= 1.05; |
第一个失败了(显然,我正试图隐式地将一个float强制转换为int)。但是第二个非常好。编译器没有抱怨,也没有收到任何运行时错误。为什么第二个有效,而第一个无效?据我所知,
复合赋值运算符的行为与它们的"扩展"版本稍有不同。引用JLS第15.26.2节:
A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T) ((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.
它隐式转换回左侧变量的类型,因此将
Assignment contexts allow the use of one of the following:
an identity conversion (§5.1.1)
a widening primitive conversion (§5.1.2)
a widening reference conversion (§5.1.5)
a boxing conversion (§5.1.7) optionally followed by a widening reference conversion
an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.
接着讨论了一种可能的变窄转换,但仅限于常数表达式,并且仅限于常数表达式为
第一个
1 2 | int score = 100; score = score * 1.05; |
基本上是说:
1 2 | int score = 100; score = (float)(score * 1.05); |
这是因为如果用一个整数乘以一个浮点数,就会得到一个浮点数。这样就无法分配给整数。
然而
1 2 | int score = 100; score *= 1.05; |
基本上意味着
1 2 | int score = 100; score = (int)(score * 1.05); |
这是因为您没有分配浮点,计算是在分配的同时完成的,因此首先将转换为int。
这对我来说是有意义的。希望它有帮助
如果使用:
1 2 | int score=100; score *=1.05; |
这相当于:
1 | score=(int)(score*1.05); |
这里更详细地解释了:http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html 15.26.2
形式e1 op=e2的复合赋值表达式等价于e1=(t)((e1)op(e2)),其中t是e1的类型,但e1只计算一次。