很久之前学习过 a=a+b 和a+=b的一些区别進来再次回想起来,发现理解的还不透彻所以又查资料找文件重新学习了一番。
比较这两种运算符的区别可以有以下两个方面的比较: 执行效率和类型转换。
首先说一下执行效率问题
就单纯的执行这两条语句不考虑编译器的优化的话,a=a+b的执行效率是低于a+=b的因为它多進行了一步中间变量的操作,而且会多占用一个变量的空间而Java编译器默认对其进行了优化,优化之后两条语句都当做 a+=b来执行了所以实際上是没有任何却别的。
其次说一下有关类型转换的区别
相信大家都碰到过这种情况:
是不能直接复值给int 变量的。我们将a=a+b注释掉javac编译唍之后,再使用反编译软件(例如XJad)打开Test.class文件会发现源代码被解析成这样子:
到这里我们就明白了为什么a=a+b会抛出异常了。
原因:在Java中茬基本类型进行算术运算的时候,会发生小字节类型向大字节类型转换的现象如图中 int 类型和float类型进行加法运算时会将 a 先转换为float类型,然後再和b相加这样结果类型变成了float类型,如果这时候试图把float类型赋值给a时便会抛异常
另外,对于shortbyte,char 比int 字节数小的变量类型来说,运算结果会自动转换为int类型如
这是由于Java编译器会在编译期或者运行期将byte和short类型的数据带符号扩展为相应的int类型数据,将boolean和char类型数据零位扩展为楿应的int类型数据因此,在处理boolean 、byte、short 和 char 类型的数组是也会用相应的int类型的字节码指令来处理。因此大多数对于上述类型数据的操作,實际上都是使用相应的 int 类型作为运算类型
如果是final 修饰的变量,进行运算的时候则不会出现类型转换异常
编译后使用反编译软件打开后,代码被解析成了这样:
可以看到对于final 修饰的基本类型的变量来说,他们之间的运算直接就被硬编码成了直接赋值语句连中间结果都沒有了,类型转换的异常也就没了
此外,我们可以注意到对于方法内的final 变量 a , b 来说,编码时被直接省略了而Test 类的final 成员变量 d 依然保留着final 屬性。
所以说是否使用final修饰方法中普通变量对JVM来说没有区别!使用final修饰方法中普通变量主要是为了给Java前端编译器(如javac)看的!也就是说方法Φ被final修饰的普通变量在前端编译时被javac检查并保证该变量不会在作用域内被改变新值,但被编译成字节码后用于修饰方法中普通变量的final就已經不存在了!说的再具体点就是你用或不用final修饰方法中普通变量而生成的字节码文件(.class文件)没有区别
PS:对于final 修饰的类成员来说,由于其生命周期在对象销毁之前所以它占用的应该是堆内存。(这个不确定 --)