很久之前學習過 a=a+b 和a+=b的一些區(qū)別,進來再次回想起來,發(fā)現(xiàn)理解的還不透徹,所以又查資料找文件重新學習了一番。 比較這兩種運算符的區(qū)別,可以有以下兩個方面的比較: 執(zhí)行效率和類型轉(zhuǎn)換。 首先說一下執(zhí)行效率問題 就單純的執(zhí)行這兩條語句,不考慮編譯器的優(yōu)化的話,a=a+b的執(zhí)行效率是低于a+=b的,因為它多進行了一步中間變量的操作,而且會多占用一個變量的空間。而Java編譯器默認對其進行了優(yōu)化,優(yōu)化之后兩條語句都當做 a+=b來執(zhí)行了,所以實際上是沒有任何卻別的。 其次說一下有關(guān)類型轉(zhuǎn)換的區(qū)別。 相信大家都碰到過這種情況: public class Test { 當使用a=a+b的時候,會拋出”Exception in thread "main" java.lang.Error: Unresolved compilation problem: Type mismatch: cannot convert from float to int“的異常,這是可以理解的,如果不使用(int)強制類型轉(zhuǎn)換的話,float 是不能直接復值給int 變量的。 我們將a=a+b注釋掉,javac編譯完之后,再使用反編譯軟件(例如XJad)打開Test.class文件,會發(fā)現(xiàn)源代碼被解析成這樣子: public class Test public Test() public static void main(String args[]) 即a+=b進行了強制類型轉(zhuǎn)換,和 a=(int)((float)a+b)是等價的! 到這里我們就明白了為什么a=a+b會拋出異常了。 原因:在Java中,在基本類型進行算術(shù)運算的時候,會發(fā)生小字節(jié)類型向大字節(jié)類型轉(zhuǎn)換的現(xiàn)象。如圖中 int 類型和float類型進行加法運算時會將 a 先轉(zhuǎn)換為float類型,然后再和b相加。這樣結(jié)果類型變成了float類型,如果這時候試圖把float類型賦值給a時便會拋異常。 另外,對于short,byte,char 比int 字節(jié)數(shù)小的變量類型來說,運算結(jié)果會自動轉(zhuǎn)換為int類型,如 byte a = 1 , b=2; byte a = 1; 都會拋出”Exception in thread "main" java.lang.Error: Unresolved compilation problem: Type mismatch: cannot convert from int to byte“類似的異常,可以看出a+b結(jié)果變成了int類型。 這是由于Java編譯器會在編譯期或者運行期將byte和short類型的數(shù)據(jù)帶符號擴展為相應(yīng)的int類型數(shù)據(jù),將boolean和char類型數(shù)據(jù)零位擴展為相應(yīng)的int類型數(shù)據(jù)。因此,在處理boolean 、byte、short 和 char 類型的數(shù)組是,也會用相應(yīng)的int類型的字節(jié)碼指令來處理。因此,大多數(shù)對于上述類型數(shù)據(jù)的操作,實際上都是使用相應(yīng)的 int 類型作為運算類型。 如果是final 修飾的變量,進行運算的時候則不會出現(xiàn)類型轉(zhuǎn)換異常。 public class Test { 編譯后使用反編譯軟件打開后,代碼被解析成了這樣: public class Test final int d = 3; public Test() public static void main(String args[]) 可以看到,對于final 修飾的基本類型的變量來說,他們之間的運算直接就被硬編碼成了直接賦值語句,連中間結(jié)果都沒有了,類型轉(zhuǎn)換的異常也就沒了。 此外,我們可以注意到,對于方法內(nèi)的final 變量 a , b 來說,編碼時被直接省略了。而Test 類的final 成員變量 d 依然保留著final 屬性。 所以說,是否使用final修飾方法中普通變量對JVM來說沒有區(qū)別!使用final修飾方法中普通變量主要是為了給Java前端編譯器(如javac)看的!也就是說方法中被final修飾的普通變量在前端編譯時被javac檢查并保證該變量不會在作用域內(nèi)被改變新值,但被編譯成字節(jié)碼后用于修飾方法中普通變量的final就已經(jīng)不存在了!說的再具體點就是你用或不用final修飾方法中普通變量而生成的字節(jié)碼文件(.class文件)沒有區(qū)別。 PS:對于final 修飾的類成員來說,由于其生命周期在對象銷毀之前,所以它占用的應(yīng)該是堆內(nèi)存。(這個不確定 --) Java 9 的新特性發(fā)布 http://www./Linux/2014-08/105707.htm Java編程思想(第4版) 中文清晰PDF完整版 http://www./Linux/2014-08/105403.htm 編寫高質(zhì)量代碼 改善Java程序的151個建議 PDF高清完整版 http://www./Linux/2014-06/103388.htm Java 8簡明教程 http://www./Linux/2014-03/98754.htm Java對象初始化順序的簡單驗證 http://www./Linux/2014-02/96220.htm Java對象值傳遞和對象傳遞的總結(jié) http://www./Linux/2012-12/76692.htm 本文永久更新鏈接地址:http://www./Linux/2014-09/106764.htm |
|
來自: Baruch > 《軟件開發(fā)》