如需转载,请标明转载来源,总结和码字都不易啊!
Java中,i += 1、i = i + 1和i++有何区别?
今天在思考i += 1和i = i + 1的区别时,自己通过比较多种方式在编译期和字节码层面的差异,总结了本篇博客(纯原创!),本篇博客的所有实验都基于JDK8,不同版本的结果可能不同。当然本人水平有限(小白),可能有错误的地方,建议大家一起尝试一遍,看看大家的结果和结论是不是一样的,欢迎交流和指正,谢谢各位啦!
Java中的整型类型默认为int,因此在对byte类型进行计算时,byte类型会自动转成int。很多人应该都知道这一点,下面带着这句话一起来看看下面这8种情况,并探究它们的区别吧!
(1)
public void method1(){
byte a = 1;
a = a + 1; // 会报错,因为int无法直接给byte类型赋值,编译无法通过
}
(2)
public void method2(){
byte a = 1;
byte b = a + 1; // 会报错,此时a+1的结果已经是int类型了(本质和前一种情况是类似的)
}
(3)
public void method3(){
byte a = 1;
int b = a + 1; // 不会报错,用int接收没问题
}
method3的字节码如下:
(4)
public void method4(){
final byte a = 1;
byte b = a + 1; // 不会报错,因为a被final修饰了,编译器可以判断b的值仍是byte类型,相当于byte b = 1 + 1;
}
method4的字节码如下:
(5)
public void method5(){
byte a = 1;
a += 1; // 不会报错,通过字节码可以看到a += 1比int b = a + 1多了i2b,也就是做了窄化类型转换,猜测应该是把做了加法后将int又转成了byte类型,因此没问题;(这里由于byte a = a + 1编译不能通过,所以我是通过int b = a + 1来看字节码的,这里本质应该是一样的)
}
method5的字节码如下:
(6)
public void method6(){
int a = 1;
a += 1; // 最常规的情况,不会报错;
}
method6的字节码如下:
(7)
public void method7(){
int a = 1;
a = a + 1;
}
method7字节码如下:
(8)
public void method8(){
int a = 1;
a++;
}
method8字节码如下:
总结(比较粗浅,以后有时间会继续完善补充):
通过上述8个方法,我们可以在前2个方法编译期的报错信息,以及后6个方法的字节码中,发现:
(1)method1和2报错的原因是等式右边的结果已经是int类型了;
(2)从method4的字节码可以看出a被final修饰后已经是常量了,byte类型的常量与常量加减,不会转成int类型;
(3)从method5和6可以看出,int类型的a和byte类型的a即使都是进行a += 1的操作,字节码层面是不同的;
(4)对比method3和5可以看出,byte类型的a在a += 1和int b = a + 1时字节码层面是不一样的,a += 1会多一步窄化操作,所以即使不用int接收也不会报错;
(5)对比method6和7,可以发现a += 1比a = a + 1在字节码层面确实步骤少了很多,理论效率更高(具体有什么区别以后有空详细分析一下);
(6)对比method6和8,可以发现a += 1和a++在字节码层面是相同的;