一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - Java中自動裝箱、拆箱引起的耗時詳解

Java中自動裝箱、拆箱引起的耗時詳解

2021-07-29 11:38veryitman Java教程

這篇文章主要給大家介紹了關于Java中自動裝箱、拆箱引起的耗時的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Java具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

什么是自動裝箱,拆箱

先拋出定義,java中基礎數據類型與它們的包裝類進行運算時,編譯器會自動幫我們進行轉換,轉換過程對程序員是透明的,這就是裝箱和拆箱,裝箱和拆箱可以讓我們的代碼更簡潔易懂

耗時問題

在說 java 的自動裝箱和自動拆箱之前,我們先看一個例子。

這個錯誤我在項目中犯過(尷尬),拿出來共勉!

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

 

自動裝箱示例:

?
1
2
int a = 3;
integer b = a;

自動拆箱示例:

?
1
2
integer b = new integer(7);
int a = b;

integer/int 自動拆箱和裝箱

下面這段代碼是 integer 的源碼中 valueof 方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * 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);
}

我們在執行下面的這句代碼,如下:

?
1
integer i = 100;

上面的代碼等同于下面的代碼:

?
1
integer i = integer.valueof(100);

結合上面的源碼可以看出來,如果數值在 [-128,127] 之間(雙閉區間),不會重新創建 integer 對象,而是從緩存中(常量池)直接獲取,從常量池中獲取而不是堆棧操作,讀取數據要快很多。

我們再來看一下常見的基礎面試題(請給出打印結果),如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 方法,源碼如下:

?
1
2
3
4
5
6
7
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 方法有下面這句代碼,如下:

?
1
long sum = 0l;

很明顯我們聲明了一個 long 的對象 sum,由于自動裝箱,這句代碼并沒有語法上面的錯誤,編譯器當然也不會報錯。上面代碼等同于如下代碼:

?
1
long sum = long.valueof(0);

在 for 循環中,超過 [-128,127] 就會創建新的對象,這樣不斷的創建對象,不停的申請堆內存,程序執行自然也就比較耗時了。

修改一下代碼,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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");
}

執行時間大大縮短。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。

原文鏈接:http://www.veryitman.com/2019/04/07/Java-自動裝箱、拆箱引起的耗時/

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产91在线精品狼人 | 久久偷拍国2017的 | 动态图啪啪120秒免费看 | 国产综合成人久久大片91 | 国产乱叫456在线 | 99成人国产精品视频 | 亚洲视频国产精品 | 日本丰满www色 | 亚洲品质自拍网站 | 精品日韩欧美一区二区三区 | 青青草原国产视频 | 欧美日韩一区二区三区韩大 | 国人精品视频在线观看 | 男人天堂资源网 | 特黄特色一级aa毛片免费观看 | 变态女王麻麻小说在线阅读 | bbbxxx乱大交欧美小说 | 国产成人精品免费视频大全五级 | 精品精品久久宅男的天堂 | free嫩白的12sex性自由 | 图片亚洲va欧美va国产综合 | sao虎在线精品永久在线 | 亚洲一区二区精品视频 | 亚洲天堂成人在线观看 | 亚洲精品国产AV成人毛片 | 91亚洲精品久久91综合 | 久久成人永久免费播放 | sss亚洲国产欧美一区二区 | 午夜精品一区 | 美艳教师刘艳第三部166 | 久久伊人免费 | 日产乱码2021永久手机版 | 欧美精品久久一区二区三区 | 精品久久一 | 国产香蕉一区二区在线网站 | 欧美精品久久久久久久免费观看 | 精品一区二区三区免费观看 | 亚洲福利一区二区精品秒拍 | 亚洲人成综合在线播放 | 亚洲一区二区精品推荐 | 天天做天天爰夜夜爽 |