Java 效能筆記:自動裝箱/拆箱

2016-04-17    分類:JAVA開發、程式設計開發、首頁精華5人評論發表於2016-04-17

本文由碼農網 – 袁延勇原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

如果我說“僅僅修改下面程式碼中的一個字元就可以獲得五倍於當前的執行速度”你會怎麼想呢?

long t = System.currentTimeMillis();
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println("total:" + sum);
System.out.println("processing time: " + (System.currentTimeMillis() - t) + " ms") ;

結果如下:

total:2305843005992468481
processing time: 6756 ms

譯者本機測試結果:

total:2305843005992468481
processing time: 8369 ms

一番思考之後,我們可以採用如下更加快速的程式碼:

long t = System.currentTimeMillis();
//Long sum = 0L;
long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println("total:" + sum);
System.out.println("processing time: " + (System.currentTimeMillis() - t) + " ms") ;

結果如下:

total:2305843005992468481
processing time: 1248 ms

譯者本機測試結果:

total:2305843005992468481
processing time: 779 ms

我們可以將這種差異解釋為對自動裝箱功能的濫用,而此功能自JDK1.5我們就已開始使用。先不管造成差異的原因,讓我們來仔細琢磨下Java中“自動裝箱”和“自動拆箱”的概念。

Java中變數被分為兩類:基礎資料型別和引用資料型別。Java中有8種基礎資料型別和與每一種基礎資料型別相對應的8種引用資料型別(包裝類)

Primitive Types Reference Types(Wrapper Class)
boolean Boolean
byte Byte
char Character
float Float
int Integer
long Long
short Short
double Double

如下程式碼片段列舉了“自動裝箱”和“自動拆箱”的例子。程式碼片段中,一個“long”型別的值被新增到“Long”型別值的列表中。在JDK1.4中,要想執行以上操作,我們必須將基礎資料型別放到與之對應的引用資料型別中(裝箱)。JDK1.5以後,編譯器幫我們執行以上操作,所以我們節省了不少程式碼量。

List<Long> longList = new ArrayList<>();      
long i = 4;
longList.add( i ); //autoboxing      
long j = longList.get( 0 ); //unboxing

JDK1.5以後,編譯器已經自動改變上述程式碼段為以下程式碼:

List<Long> longList = new ArrayList<>();      
long i = 4;
longList.add(Long.valueOf( i ) );      
long j = longList.get( 0 ).longValue();

因此,我們可以說我們的第一段程式碼已經被修改為下面的程式碼。所以我們可以利用轉化後的程式碼(建立不必要的“Long”例項)來解釋處理速度緣何變慢。

long t = System.currentTimeMillis();
Long sum = 0L;
for (long i = 0; i < Integer.MAX_VALUE; i++) {
sum += new Long(i);
}
System.out.println("total:" + sum);
System.out.println("processing time: " + (System.currentTimeMillis() - t) + " ms") ;

結論,如果我們想要寫出處理速度更快的程式碼,我們需要仔細琢磨“自動裝箱”和“自動拆箱”的概念。

譯者注:本機使用JDK1.8,可能與筆者使用JDK版本存在差異,多次測試均保持10倍左右的處理速度差異,可見影響還是比較大的。

譯文連結:http://www.codeceo.com/article/java-autoboxing-unboxing.html
英文原文:Java Performance Notes: Autoboxing / Unboxing
翻譯作者:碼農網 – 袁延勇
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章