为什么“+=”就是强制类型转换?
大家可能在学习java基础的时候遇到过这样的经典问题:
public class Test
{
public static void main(String[] args){
short i = 0;
--------(填空)
System.out.println("i="+i);
}
}
请选择:A : i = 1 + i; B: i += 1;
答案是B,这种问题我想大家但凡有些基础的,肯定都是闭着眼睛都能做出来。
但是,接下来我会问为什么答案是B?
那么我得到的答案可能就是以下这些:
啊,因为 java中常数默认是int类型,A在进行运算的时候结果类型为int类型了,所以int类型赋值给short的变量会出现类型转换异常。但是B中,"+="运算符进行了一次类型转换,因此不会出现异常。
当然这个答案是正确的,能这样回答出来的人相信基础也确实可以,但是这个答案含糊了一个点,就是——为什么 “+=” 就进行类型转换了?他是在什么时候做的类型转换?
那么根据这两个问题,接下来我就结合着JVM来做解答!
首先根据以上问题,我们写出以下测试代码,并深入研究:
import java.util.*;
public class Test
{
public static void main(String[] args){
// 测试 += 符号
short i = 0;
i += 1;
System.out.println("i="+i);
// 测试 = 符号
int z = 0;
z = i + 3;
System.out.println(z);
}
}
然后我们cmd进行编译
javac Test.java
查看编译后的class文件
javap -c Test.class
结果如下(编译结果省略了注释内容)
在图上我们可以清晰的看到, += 的计算过程与 = 的计算过程的差异。
“+=” 的计算过程如下:
iconst_0 : 将int类型的常量0压入栈中
istort_1 : 将int类型的值存入局部变量1中
<------- 到此 short i = 0; 这一步结束,以下开始计算
iload_1: 从局部变量1里面加载int的值
iconst_1 : 将int类型的常量1压入栈中
iadd : 执行int类型的加法
i2s : 将int类型转换为short类型
istort_1 : 将int类型的值存入局部变量1中
<======================== 计算结束
“=” 的计算过程如下
iconst_0 : 将int类型的常量0压入栈中
istort_2 : 将int类型的值存入局部变量2中
<------- 到此 short i = 0; 这一步结束,以下开始计算
iload_1: 从局部变量1里面加载int的值
iconst_3 : 将int类型的常量3压入栈中
iadd : 执行int类型的加法
istort_2 : 将int类型的值存入局部变量2中
<======================== 计算结束
经过分析之后,答案变得显而易见了。
+= 符号之所以不会触发异常,是因为加执行完加法之后又进行了一次类型转换,而 = 符号则是执行完加法之后直接取存储变量了,因此会触发。 那么这个类型转换的关键就是:+= 符号经过java编译后, i2s 这条JVM指令。
这是我第一次知识记录,是我学习道路上新的开始。