您好,登錄后才能下訂單哦!
這篇文章主要介紹了Java中自動裝箱、拆箱引起耗時問題的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
什么是自動裝箱,拆箱
先拋出定義,Java中基礎數據類型與它們的包裝類進行運算時,編譯器會自動幫我們進行轉換,轉換過程對程序員是透明的,這就是裝箱和拆箱,裝箱和拆箱可以讓我們的代碼更簡潔易懂
耗時問題
在說 Java 的自動裝箱和自動拆箱之前,我們先看一個例子。
這個錯誤我在項目中犯過(尷尬),拿出來共勉!
private static long getCounterResult() { Long sum = 0L; final int length = Integer.MAX_VALUE; for (int i = 0; i < length; i++) { sum += i; } return sum; } public static void main(String[] args) { long startCountTime = System.currentTimeMillis(); long result = getCounterResult(); long endCountTime = System.currentTimeMillis(); System.out.println("result = " + result + ", and take up time : " + (endCountTime - startCountTime) / 1000 + "s"); }
在我的電腦(macOS 64位系統,配置較高),打印結果如下:
result = 2305843005992468481, and take up time : 12s
居然使用了 12s,是可忍叔不可忍,再正常不過的代碼怎么會耗時這么久呢?如果在配置差一點的電腦上運行耗時會更久(驚呆了.jpg)。
我們不妨先閱讀下面的內容,再來分析、解決上述耗時的問題。
基本概念
自從 jdk1.5 之后就有了自動裝箱(Autoboxing)和自動拆箱(AutoUnboxing)。
自動裝箱,就是 Java 自動將原始(基本)類型轉換成對應的封裝器(對象)類型的過程,比如將 int 的變量轉換成 Integer 對象,這個過程叫做裝箱。
自動拆箱,就是 Java 自動將封裝器(對象)類型轉換成基本類型的過程,如將 Integer 對象轉換成 int 類型值,這個過程叫做拆箱。
之所以稱之為自動裝箱和拆箱,是因為這些操作并非人工(程序猿)操作的,而是 Java 自帶的一個特性。
下表是 Java 中的基本類型和對應的封裝類型的對應表:
基本類型 | 封裝器類 |
---|---|
int | Integer |
byte | Byte |
long | Long |
float | float |
double | Double |
char | Character |
boolean | Boolean |
自動裝箱示例:
int a = 3; Integer b = a;
自動拆箱示例:
Integer b = new Integer(7); int a = b;
Integer/int 自動拆箱和裝箱
下面這段代碼是 Integer 的源碼中 valueOf 方法。
/** * Returns an {@code Integer} instance representing the specified * {@code int} value. If a new {@code Integer} instance is not * required, this method should generally be used in preference to * the constructor {@link #Integer(int)}, as this method is likely * to yield significantly better space and time performance by * caching frequently requested values. * * This method will always cache values in the range -128 to 127, * inclusive, and may cache other values outside of this range. * * @param i an {@code int} value. * @return an {@code Integer} instance representing {@code i}. * @since 1.5 */ public static Integer valueOf(int i) { // 如果i的值大于-128小于127則返回一個緩沖區中的一個Integer對象 if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; // 否則返回 new 一個Integer 對象 return new Integer(i); }
我們在執行下面的這句代碼,如下:
Integer i = 100;
上面的代碼等同于下面的代碼:
Integer i = Integer.valueOf(100);
結合上面的源碼可以看出來,如果數值在 [-128,127] 之間(雙閉區間),不會重新創建 Integer 對象,而是從緩存中(常量池)直接獲取,從常量池中獲取而不是堆棧操作,讀取數據要快很多。
我們再來看一下常見的基礎面試題(請給出打印結果),如下:
public static void main(String[] args) { // ? Integer a = new Integer(121); Integer b = new Integer(121); System.out.println(a == b); // ? Integer c = 121; Integer d = 121; System.out.println(c == d); // ? Integer e = 129; Integer f = 129; System.out.println(e == f); // ? int g = 50; Integer h = new Integer(50); System.out.println(g == h); }
分析結果:
?: false, 兩個對象進行比較分別指向了不同堆內存
?: true, 自動裝箱且數值在 [-128,127] 之間(雙閉區間)
?: false, 自動裝箱且數值不在 [-128,127] 之間(雙閉區間)
?: true, 自動拆箱且數值在 [-128,127] 之間(雙閉區間)
解析耗時問題
類 Long 對應的也有一個 valueof 方法,源碼如下:
public static Long valueOf(long l) { final int offset = 128; if (l >= -128 && l <= 127) { // will cache return LongCache.cache[(int)l + offset]; } return new Long(l); }
這個和 Integer 的很像,道理上面說過,這里不再贅述。
在開篇的例子中,getCounterResult 方法有下面這句代碼,如下:
Long sum = 0L;
很明顯我們聲明了一個 Long 的對象 sum,由于自動裝箱,這句代碼并沒有語法上面的錯誤,編譯器當然也不會報錯。上面代碼等同于如下代碼:
Long sum = Long.valueof(0);
在 for 循環中,超過 [-128,127] 就會創建新的對象,這樣不斷的創建對象,不停的申請堆內存,程序執行自然也就比較耗時了。
修改一下代碼,如下:
private static long getCounterResult() { // 修改為普通的基本類型數據 long sum = 0L; final int length = Integer.MAX_VALUE; for (int i = 0; i < length; i++) { sum += i; } return sum; } public static void main(String[] args) { long startCountTime = System.currentTimeMillis(); long result = getCounterResult(); long endCountTime = System.currentTimeMillis(); System.out.println("result = " + result + ", and take up time : " + (endCountTime - startCountTime) / 1000 + "s"); }
執行時間大大縮短。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“Java中自動裝箱、拆箱引起耗時問題的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。