Java中double转int的Lossy Conversion异常:为何+=运算符无报错?
为什么
+=不会触发损失转换错误? 这事儿的核心在于Java对直接赋值和**复合赋值运算符(比如+=)**的处理规则完全不同,咱们一步步拆解清楚:
先看代码示例1的报错原因
这段代码直接把Math.pow()返回的double值赋值给int变量:
class Lossy { public static void main(String args[]) { int sum; sum=Math.pow(2,3); // 这里触发Possible Lossy Conversion错误 System.out.println (sum); } }
Math.pow()返回的是double类型(比如这里的8.0),而int是范围更小的整数类型。把大范围类型直接赋值给小范围类型属于窄化转换——这种转换可能会丢失精度(比如如果结果是8.5,转成int就会丢掉小数部分变成8),所以Java编译器要求你必须显式写强制类型转换(比如sum = (int) Math.pow(2,3);),否则就会抛出错误,防止你不小心丢失数据。
再看代码示例2为什么能正常编译
修改后的代码用了+=复合赋值:
class Lossy { public static void main(String args[]) { int sum=2; sum+=Math.pow(2,3); // 这里完全没问题 System.out.println (sum); // 输出10 } }
Java语言规范里对复合赋值运算符有特殊规定:E1 op= E2这种写法,等价于E1 = (T)((E1) op (E2)),其中T是E1的类型。翻译到咱们的例子里,就是编译器会自动把代码转换成:
sum = (int)(sum + Math.pow(2,3));
具体执行步骤是:
- 先把
sum的int值2自动转换成double类型(变成2.0) - 和
Math.pow(2,3)返回的8.0相加,得到10.0 - 最后自动把这个
double结果强制转换成int类型(变成10),赋值给sum
因为复合赋值运算符会自动帮你加上强制类型转换,编译器默认你已经知晓这里可能存在精度损失并接受这种转换,所以不会再抛出错误。
内容的提问来源于stack exchange,提问作者Vedant Pareek




