日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

[转载] 什么是Java中的自动拆装箱 integer

發(fā)布時(shí)間:2025/3/11 java 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载] 什么是Java中的自动拆装箱 integer 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考鏈接: Java中autoboxing自動(dòng)裝箱整數(shù)對(duì)象的比較

本文主要介紹Java中的自動(dòng)拆箱與自動(dòng)裝箱的有關(guān)知識(shí)。?

??

1、基本數(shù)據(jù)類(lèi)型? ?

基本類(lèi)型,或者叫做內(nèi)置類(lèi)型,是Java中不同于類(lèi)(Class)的特殊類(lèi)型。它們是我們編程中使用最頻繁的類(lèi)型。?

Java是一種強(qiáng)類(lèi)型語(yǔ)言,第一次申明變量必須說(shuō)明數(shù)據(jù)類(lèi)型,第一次變量賦值稱(chēng)為變量的初始化。?

Java基本類(lèi)型共有八種,基本類(lèi)型可以分為三類(lèi):?

字符類(lèi)型char?

布爾類(lèi)型boolean?

整數(shù)類(lèi)型byte、short、int、long?

浮點(diǎn)數(shù)類(lèi)型float、double。?

Java中的數(shù)值類(lèi)型不存在無(wú)符號(hào)的,它們的取值范圍是固定的,不會(huì)隨著機(jī)器硬件環(huán)境或者操作系統(tǒng)的改變而改變。?

實(shí)際上,Java中還存在另外一種基本類(lèi)型void,它也有對(duì)應(yīng)的包裝類(lèi)java.lang.Void,不過(guò)我們無(wú)法直接對(duì)它們進(jìn)行操作。?

基本數(shù)據(jù)類(lèi)型有什么好處 我們都知道在Java語(yǔ)言中,new一個(gè)對(duì)象是存儲(chǔ)在堆里的,我們通過(guò)棧中的引用來(lái)使用這些對(duì)象;所以,對(duì)象本身來(lái)說(shuō)是比較消耗資源的。?

對(duì)于經(jīng)常用到的類(lèi)型,如int等,如果我們每次使用這種變量的時(shí)候都需要new一個(gè)Java對(duì)象的話,就會(huì)比較笨重。?

所以,和C++一樣,Java提供了基本數(shù)據(jù)類(lèi)型,這種數(shù)據(jù)的變量不需要使用new創(chuàng)建,他們不會(huì)在堆上創(chuàng)建,而是直接在棧內(nèi)存中存儲(chǔ),因此會(huì)更加高效。?

整型的取值范圍?

Java中的整型主要包含byte、short、int和long這四種,表示的數(shù)字范圍也是從小到大的,之所以表示范圍不同主要和他們存儲(chǔ)數(shù)據(jù)時(shí)所占的字節(jié)數(shù)有關(guān)。?

先來(lái)個(gè)簡(jiǎn)答的科普,1字節(jié)=8位(bit)。java中的整型屬于有符號(hào)數(shù)。?

先來(lái)看計(jì)算中8bit可以表示的數(shù)字:?

最小值:10000000 (-128)(-2^7) 最大值:01111111(127)(2^7-1) 整型的這幾個(gè)類(lèi)型中,?

byte:byte用1個(gè)字節(jié)來(lái)存儲(chǔ),范圍為-128(-2^7)到127(2^7-1),在變量初始化的時(shí)候,byte類(lèi)型的默認(rèn)值為0。?

short:short用2個(gè)字節(jié)存儲(chǔ),范圍為-32,768 (-2^15)到32,767 (2^15-1),在變量初始化的時(shí)候,short類(lèi)型的默認(rèn)值為0,一般情況下,因?yàn)镴ava本身轉(zhuǎn)型的原因,可以直接寫(xiě)為0。?

int:int用4個(gè)字節(jié)存儲(chǔ),范圍為-2,147,483,648 (-2^31)到2,147,483,647 (2^31-1),在變量初始化的時(shí)候,int類(lèi)型的默認(rèn)值為0。?

long:long用8個(gè)字節(jié)存儲(chǔ),范圍為-9,223,372,036,854,775,808 (-2^63)到9,223,372,036, 854,775,807 (2^63-1),在變量初始化的時(shí)候,long類(lèi)型的默認(rèn)值為0L或0l,也可直接寫(xiě)為0。?

超出范圍怎么辦 上面說(shuō)過(guò)了,整型中,每個(gè)類(lèi)型都有一定的表示范圍,但是,在程序中有些計(jì)算會(huì)導(dǎo)致超出表示范圍,即溢出。如以下代碼:?

int i = Integer.MAX_VALUE;

int j = Integer.MAX_VALUE;

?

int k = i + j;

System.out.println("i (" + i + ") + j (" + j + ") = k (" + k + ")");?

輸出結(jié)果:i (2147483647) + j (2147483647) = k (-2)?

這就是發(fā)生了溢出,溢出的時(shí)候并不會(huì)拋異常,也沒(méi)有任何提示。所以,在程序中,使用同類(lèi)型的數(shù)據(jù)進(jìn)行運(yùn)算的時(shí)候,一定要注意數(shù)據(jù)溢出的問(wèn)題。?

??

2、包裝類(lèi)型?

Java語(yǔ)言是一個(gè)面向?qū)ο蟮恼Z(yǔ)言,但是Java中的基本數(shù)據(jù)類(lèi)型卻是不面向?qū)ο蟮?#xff0c;這在實(shí)際使用時(shí)存在很多的不便,為了解決這個(gè)不足,在設(shè)計(jì)類(lèi)時(shí)為每個(gè)基本數(shù)據(jù)類(lèi)型設(shè)計(jì)了一個(gè)對(duì)應(yīng)的類(lèi)進(jìn)行代表,這樣八個(gè)和基本數(shù)據(jù)類(lèi)型對(duì)應(yīng)的類(lèi)統(tǒng)稱(chēng)為包裝類(lèi)(Wrapper Class)。?

包裝類(lèi)均位于java.lang包,包裝類(lèi)和基本數(shù)據(jù)類(lèi)型的對(duì)應(yīng)關(guān)系如下表所示?

基本數(shù)據(jù)類(lèi)型? ? 包裝類(lèi)?

byte? ? ? ? ? Byte

boolean? ? ? ?Boolean

short? ? ? ? ?Short

char? ? ? ? ? Character

int? ? ? ? ? ?Integer

long? ? ? ? ? Long

float? ? ? ? ?Float

double? ? ? ? Double?

?在這八個(gè)類(lèi)名中,除了Integer和Character類(lèi)以后,其它六個(gè)類(lèi)的類(lèi)名和基本數(shù)據(jù)類(lèi)型一致,只是類(lèi)名的第一個(gè)字母大寫(xiě)即可。?

為什么需要包裝類(lèi) 很多人會(huì)有疑問(wèn),既然Java中為了提高效率,提供了八種基本數(shù)據(jù)類(lèi)型,為什么還要提供包裝類(lèi)呢??

這個(gè)問(wèn)題,其實(shí)前面已經(jīng)有了答案,因?yàn)镴ava是一種面向?qū)ο笳Z(yǔ)言,很多地方都需要使用對(duì)象而不是基本數(shù)據(jù)類(lèi)型。比如,在集合類(lèi)中,我們是無(wú)法將int 、double等類(lèi)型放進(jìn)去的。因?yàn)榧系娜萜饕笤厥荗bject類(lèi)型。?

為了讓基本類(lèi)型也具有對(duì)象的特征,就出現(xiàn)了包裝類(lèi)型,它相當(dāng)于將基本類(lèi)型“包裝起來(lái)”,使得它具有了對(duì)象的性質(zhì),并且為其添加了屬性和方法,豐富了基本類(lèi)型的操作。?

??

3、拆箱與裝箱?

那么,有了基本數(shù)據(jù)類(lèi)型和包裝類(lèi),肯定有些時(shí)候要在他們之間進(jìn)行轉(zhuǎn)換。比如把一個(gè)基本數(shù)據(jù)類(lèi)型的int轉(zhuǎn)換成一個(gè)包裝類(lèi)型的Integer對(duì)象。?

我們認(rèn)為包裝類(lèi)是對(duì)基本類(lèi)型的包裝,所以,把基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換成包裝類(lèi)的過(guò)程就是打包裝,英文對(duì)應(yīng)于boxing,中文翻譯為裝箱。?

反之,把包裝類(lèi)轉(zhuǎn)換成基本數(shù)據(jù)類(lèi)型的過(guò)程就是拆包裝,英文對(duì)應(yīng)于unboxing,中文翻譯為拆箱。?

在Java SE5之前,要進(jìn)行裝箱,可以通過(guò)以下代碼:?

Integer i = new Integer(10);?

??

4、自動(dòng)拆箱與自動(dòng)裝箱?

在Java SE5中,為了減少開(kāi)發(fā)人員的工作,Java提供了自動(dòng)拆箱與自動(dòng)裝箱功能。?

自動(dòng)裝箱: 就是將基本數(shù)據(jù)類(lèi)型自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的包裝類(lèi)。?

自動(dòng)拆箱:就是將包裝類(lèi)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的基本數(shù)據(jù)類(lèi)型。?

Integer i =10;? //自動(dòng)裝箱

int b= i;? ? ?//自動(dòng)拆箱?

Integer i=10 可以替代 Integer i = new Integer(10); 這就是因?yàn)镴ava幫我們提供了自動(dòng)裝箱的功能,不需要開(kāi)發(fā)者手動(dòng)去new一個(gè)Integer對(duì)象。?

??

5、自動(dòng)裝箱與自動(dòng)拆箱的實(shí)現(xiàn)原理?

既然Java提供了自動(dòng)拆裝箱的能力,那么,我們就來(lái)看一下,到底是什么原理,Java是如何實(shí)現(xiàn)的自動(dòng)拆裝箱功能。?

我們有以下自動(dòng)拆裝箱的代碼:?

public static? void main(String[]args){

? ? Integer integer=1; //裝箱

? ? int i=integer; //拆箱

}

對(duì)以上代碼進(jìn)行反編譯后可以得到以下代碼:

?

public static? void main(String[]args){

? ? Integer integer=Integer.valueOf(1);?

? ? int i=integer.intValue();?

}?

?從上面反編譯后的代碼可以看出,int的自動(dòng)裝箱都是通過(guò)Integer.valueOf()方法來(lái)實(shí)現(xiàn)的,Integer的自動(dòng)拆箱都是通過(guò)integer.intValue來(lái)實(shí)現(xiàn)的。如果讀者感興趣,可以試著將八種類(lèi)型都反編譯一遍 ,你會(huì)發(fā)現(xiàn)以下規(guī)律:?

自動(dòng)裝箱都是通過(guò)包裝類(lèi)的valueOf()方法來(lái)實(shí)現(xiàn)的.自動(dòng)拆箱都是通過(guò)包裝類(lèi)對(duì)象的xxxValue()來(lái)實(shí)現(xiàn)的。?

6、哪些地方會(huì)自動(dòng)拆裝箱?

我們了解過(guò)原理之后,在來(lái)看一下,什么情況下,Java會(huì)幫我們進(jìn)行自動(dòng)拆裝箱。前面提到的變量的初始化和賦值的場(chǎng)景就不介紹了,那是最簡(jiǎn)單的也最容易理解的。?

我們主要來(lái)看一下,那些可能被忽略的場(chǎng)景。?

場(chǎng)景一、將基本數(shù)據(jù)類(lèi)型放入集合類(lèi)?

我們知道,Java中的集合類(lèi)只能接收對(duì)象類(lèi)型,那么以下代碼為什么會(huì)不報(bào)錯(cuò)呢??

List<Integer> li = new ArrayList<>();

for (int i = 1; i < 50; i ++){

? ? li.add(i);

}?

將上面代碼進(jìn)行反編譯,可以得到以下代碼:?

List<Integer> li = new ArrayList<>();

for (int i = 1; i < 50; i += 2){

? ? li.add(Integer.valueOf(i));

}?

以上,我們可以得出結(jié)論,當(dāng)我們把基本數(shù)據(jù)類(lèi)型放入集合類(lèi)中的時(shí)候,會(huì)進(jìn)行自動(dòng)裝箱。?

場(chǎng)景二、包裝類(lèi)型和基本類(lèi)型的大小比較?

有沒(méi)有人想過(guò),當(dāng)我們對(duì)Integer對(duì)象與基本類(lèi)型進(jìn)行大小比較的時(shí)候,實(shí)際上比較的是什么內(nèi)容呢?看以下代碼:?

I?

Integer a=1;

System.out.println(a==1?"等于":"不等于");

Boolean bool=false;

System.out.println(bool?"真":"假");?

對(duì)以上代碼進(jìn)行反編譯,得到以下代碼:?

Integer a=1;

System.out.println(a.intValue()==1?"等于":"不等于");

Boolean bool=false;

System.out.println(bool.booleanValue?"真":"假");?

可以看到,包裝類(lèi)與基本數(shù)據(jù)類(lèi)型進(jìn)行比較運(yùn)算,是先將包裝類(lèi)進(jìn)行拆箱成基本數(shù)據(jù)類(lèi)型,然后進(jìn)行比較的。?

場(chǎng)景三、包裝類(lèi)型的運(yùn)算?

有沒(méi)有人想過(guò),當(dāng)我們對(duì)Integer對(duì)象進(jìn)行四則運(yùn)算的時(shí)候,是如何進(jìn)行的呢?看以下代碼:?

Integer i = 10;

Integer j = 20;

System.out.println(i+j);?

反編譯后代碼如下:?

Integer i = Integer.valueOf(10);

Integer j = Integer.valueOf(20);

System.out.println(i.intValue() + j.intValue());?

我們發(fā)現(xiàn),兩個(gè)包裝類(lèi)型之間的運(yùn)算,會(huì)被自動(dòng)拆箱成基本類(lèi)型進(jìn)行。?

場(chǎng)景四、三目運(yùn)算符的使用?

這是很多人不知道的一個(gè)場(chǎng)景,作者也是一次線上的血淋淋的Bug發(fā)生后才了解到的一種案例。看一個(gè)簡(jiǎn)單的三目運(yùn)算符的代碼:?

boolean flag = true;

Integer i = 0;

int j = 1;

int k = flag ? i : j;?

很多人不知道,其實(shí)在int k = flag ? i : j;這一行,會(huì)發(fā)生自動(dòng)拆箱。反編譯后代碼如下:?

boolean flag = true;

Integer i = Integer.valueOf(0);

int j = 1;

int k = flag ? i.intValue() : j;?

這其實(shí)是三目運(yùn)算符的語(yǔ)法規(guī)范:當(dāng)?shù)诙?#xff0c;第三位操作數(shù)分別為基本類(lèi)型和對(duì)象時(shí),其中的對(duì)象就會(huì)拆箱為基本類(lèi)型進(jìn)行操作。?

因?yàn)槔又?#xff0c;flag ? i : j;片段中,第二段的i是一個(gè)包裝類(lèi)型的對(duì)象,而第三段的j是一個(gè)基本類(lèi)型,所以會(huì)對(duì)包裝類(lèi)進(jìn)行自動(dòng)拆箱。如果這個(gè)時(shí)候i的值為null,那么久會(huì)發(fā)生NPE。(自動(dòng)拆箱導(dǎo)致空指針異常)?

場(chǎng)景五、函數(shù)參數(shù)與返回值?

這個(gè)比較容易理解,直接上代碼了:?

//自動(dòng)拆箱

public int getNum1(Integer num) {

?return num;

}

//自動(dòng)裝箱

public Integer getNum2(int num) {

?return num;

}?

7、自動(dòng)拆裝箱與緩存?

Java SE的自動(dòng)拆裝箱還提供了一個(gè)和緩存有關(guān)的功能,我們先來(lái)看以下代碼,猜測(cè)一下輸出結(jié)果:?

public static void main(String... strings) {

?

? ? Integer integer1 = 3; //通過(guò)反編譯發(fā)現(xiàn)執(zhí)行的是? Integer.valueOf(1);?

? ? Integer integer2 = 3;

?

? ? if (integer1 == integer2)

? ? ? ? System.out.println("integer1 == integer2");

? ? else

? ? ? ? System.out.println("integer1 != integer2");

?

? ? Integer integer3 = 300;

? ? Integer integer4 = 300;

?

? ? if (integer3 == integer4)

? ? ? ? System.out.println("integer3 == integer4");

? ? else

? ? ? ? System.out.println("integer3 != integer4");

?

}?

我們普遍認(rèn)為上面的兩個(gè)判斷的結(jié)果都是false。雖然比較的值是相等的,但是由于比較的是對(duì)象,而對(duì)象的引用不一樣,所以會(huì)認(rèn)為兩個(gè)if判斷都是false的。?

在Java中,==比較的是對(duì)象應(yīng)用,而equals比較的是值。?

所以,在這個(gè)例子中,不同的對(duì)象有不同的引用,所以在進(jìn)行比較的時(shí)候都將返回false。奇怪的是,這里兩個(gè)類(lèi)似的if條件判斷返回不同的布爾值。?

上面這段代碼真正的輸出結(jié)果:?

integer1 == integer2 integer3 != integer4 原因就和Integer中的緩存機(jī)制有關(guān)。在Java 5中,在Integer的操作上引入了一個(gè)新功能來(lái)節(jié)省內(nèi)存和提高性能。整型對(duì)象通過(guò)使用相同的對(duì)象引用實(shí)現(xiàn)了緩存和重用。?

適用于整數(shù)值區(qū)間-128 至 +127。?

只適用于自動(dòng)裝箱。使用構(gòu)造函數(shù)創(chuàng)建對(duì)象不適用。?

具體的代碼實(shí)現(xiàn)可以閱讀Java中整型的緩存機(jī)制一文,這里不再闡述。?

-- 源碼

?public static Integer valueOf(int i) {

? ? ? ? assert IntegerCache.high >= 127;

? ? ? ? if (i >= IntegerCache.low && i <= IntegerCache.high)

? ? ? ? ? ? return IntegerCache.cache[i + (-IntegerCache.low)];

? ? ? ? return new Integer(i);

? }?

我們只需要知道,當(dāng)需要進(jìn)行自動(dòng)裝箱時(shí),如果數(shù)字在-128至127之間時(shí),會(huì)直接使用緩存中的對(duì)象,而不是重新創(chuàng)建一個(gè)對(duì)象。?

擴(kuò)展:??

? ? ? ? int i =50;

? ? ? ? Integer i1 =50;

? ? ? ? Integer i2 =50;

? ? ? ? Integer i3 = new Integer(50);

? ? ? ? Integer i4 = new Integer(50);

? ? ? ? Integer i5 = 300;

? ? ? ? Integer i6 = 300;

? ? ? ? System.out.println(i == i1);// true;i1 自動(dòng)拆箱變成基本類(lèi)型,兩基本類(lèi)型比較值

? ? ? ? System.out.println(i == i3);// true; i3自動(dòng)拆箱變成基本類(lèi)型,兩基本類(lèi)型比較值

? ? ? ? System.out.println(i1 == i2);// true; i1和i3都指向常量池中同一個(gè)地址

? ? ? ? System.out.println(i1 == i3);// false; 兩個(gè)不同的對(duì)象

? ? ? ? System.out.println(i3 == i4);// false; 兩個(gè)不同的對(duì)象

? ? ? ? System.out.println(i5 == i6);// false; 自動(dòng)裝箱時(shí),如果值不在-128到127,就會(huì)創(chuàng)建一個(gè)新的對(duì)象

? ? System.out.println( "11".equals( 11 ));//false; 不同類(lèi)型之間的額比較?

其中的javadoc詳細(xì)的說(shuō)明了緩存支持-128到127之間的自動(dòng)裝箱過(guò)程。最大值127可以通過(guò)-XX:AutoBoxCacheMax=size修改。緩存通過(guò)一個(gè) for 循環(huán)實(shí)現(xiàn)。從小到大的創(chuàng)建盡可能多的整數(shù)并存儲(chǔ)在一個(gè)名為 cache 的整數(shù)數(shù)組中。這個(gè)緩存會(huì)在 Integer 類(lèi)第一次被使用的時(shí)候被初始化出來(lái)。以后就可以使用緩存中包含的實(shí)例對(duì)象,而不是創(chuàng)建一個(gè)新的實(shí)例(在自動(dòng)裝箱的情況下)。?

實(shí)際上這個(gè)功能在Java 5中引入的時(shí)候,范圍是固定的-128 至 +127。后來(lái)在Java 6中,可以通過(guò)java.lang.Integer.IntegerCache.high設(shè)置最大值。這使我們可以根據(jù)應(yīng)用程序的實(shí)際情況靈活地調(diào)整來(lái)提高性能。到底是什么原因選擇這個(gè)-128到127范圍呢?因?yàn)檫@個(gè)范圍的數(shù)字是最被廣泛使用的。 在程序中,第一次使用Integer的時(shí)候也需要一定的額外時(shí)間來(lái)初始化這個(gè)緩存。?

/**?

?* Cache to support the object identity semantics of autoboxing for values between?

?* -128 and 127 (inclusive) as required by JLS.?

?*?

?* The cache is initialized on first usage.? The size of the cache?

?* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.?

?* During VM initialization, java.lang.Integer.IntegerCache.high property?

?* may be set and saved in the private system properties in the?

?* sun.misc.VM class.?

?*/??

??

private static class IntegerCache {??

? ? static final int low = -128;??

? ? static final int high;??

? ? static final Integer cache[];??

??

? ? static {??

? ? ? ? // high value may be configured by property??

? ? ? ? int h = 127;??

? ? ? ? String integerCacheHighPropValue =??

? ? ? ? ? ? sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");??

? ? ? ? if (integerCacheHighPropValue != null) {??

? ? ? ? ? ? try {??

? ? ? ? ? ? ? ? int i = parseInt(integerCacheHighPropValue);??

? ? ? ? ? ? ? ? i = Math.max(i, 127);??

? ? ? ? ? ? ? ? // Maximum array size is Integer.MAX_VALUE??

? ? ? ? ? ? ? ? h = Math.min(i, Integer.MAX_VALUE - (-low) -1);??

? ? ? ? ? ? } catch( NumberFormatException nfe) {??

? ? ? ? ? ? ? ? // If the property cannot be parsed into an int, ignore it.??

? ? ? ? ? ? }??

? ? ? ? }??

? ? ? ? high = h;??

??

? ? ? ? cache = new Integer[(high - low) + 1];??

? ? ? ? int j = low;??

? ? ? ? for(int k = 0; k < cache.length; k++)??

? ? ? ? ? ? cache[k] = new Integer(j++);??

??

? ? ? ? // range [-128, 127] must be interned (JLS7 5.1.7)??

? ? ? ? assert IntegerCache.high >= 127;??

? ? }??

??

? ? private IntegerCache() {}??

}? ?

在Boxing Conversion部分的Java語(yǔ)言規(guī)范(JLS)規(guī)定如下:?

如果一個(gè)變量p的值是:?

-128至127之間的整數(shù)(§3.10.1)? ?true 和 false的布爾值 (§3.10.3)? ?‘\u0000’至 ‘\u007f’之間的字符(§3.10.4) 范圍內(nèi)的時(shí),將p包裝成a和b兩個(gè)對(duì)象時(shí),可以直接使用a==b判斷a和b的值是否相等。?

補(bǔ)充:??

?注意,Integer、Short、Byte、Character、Long這幾個(gè)類(lèi)的valueOf方法的實(shí)現(xiàn)是類(lèi)似的。? Double、Float的valueOf方法的實(shí)現(xiàn)是類(lèi)似的。?

而其中double和float又有所不同,我們就以double為例子,貼出代碼討論:?

public class Test {

? /**

? ?* Double

? ?*/

? public static void first() {

? ? Double i1 = 100.0;

? ? Double i2 = 100.0;

? ? Double i3 = 200.0;

? ? Double i4 = 200.0;

? ? System.out.println(i1 == i2);//false

? ? System.out.println(i3 == i4);//false

? }

? /**

? ?* 測(cè)試方法

? ?*/

? public static void main(String[] args) {

? ? first();

? }

}

?

注意為什么上面的代碼的輸出結(jié)果都是false呢?同樣的我們依舊以Double類(lèi)中的valueOf方法來(lái)討論,貼出源碼就一目了然了:

?

??

? public static Double valueOf(double d) {

? ? return new Double(d);

? }

也就是說(shuō)不管你的double是什么范圍的值,他都是給你返回一個(gè)新的對(duì)象。float同double,就不過(guò)多贅述了。?

??

8、自動(dòng)拆裝箱帶來(lái)的問(wèn)題? ?

當(dāng)然,自動(dòng)拆裝箱是一個(gè)很好的功能,大大節(jié)省了開(kāi)發(fā)人員的精力,不再需要關(guān)心到底什么時(shí)候需要拆裝箱。但是,他也會(huì)引入一些問(wèn)題。包裝對(duì)象的數(shù)值比較,不能簡(jiǎn)單的使用==,雖然-128到127之間的數(shù)字可以,但是這個(gè)范圍之外還是需要使用equals比較。?

前面提到,有些場(chǎng)景會(huì)進(jìn)行自動(dòng)拆裝箱,同時(shí)也說(shuō)過(guò),由于自動(dòng)拆箱,如果包裝類(lèi)對(duì)象為null,那么自動(dòng)拆箱時(shí)就有可能拋出NPE。?

如果一個(gè)for循環(huán)中有大量拆裝箱操作,會(huì)浪費(fèi)很多資源。?

性能問(wèn)題

首先在堆內(nèi)存中創(chuàng)建對(duì)象的消耗肯定是要比使用棧內(nèi)存要多的,同時(shí)在自動(dòng)拆裝箱的時(shí)候,也有一定的性能消耗,如果在數(shù)據(jù)量比較大,或者是循環(huán)的情況下,頻繁的拆裝箱并且生成包裝類(lèi)的時(shí)候,對(duì)性能的影響就是一星半點(diǎn)了,所以不是特殊的需求,例如上述被集合持有的情況,還是使用基本類(lèi)型而不是包裝類(lèi)?

在循環(huán)的時(shí)候?

Integer sum = 0;

?for(int i=1000; i<5000; i++){

? ?sum+=i;

}?

上面的代碼sum+=i可以看成sum = sum + i,在sum被+操作符操作的時(shí)候,會(huì)對(duì)sum進(jìn)行自動(dòng)拆箱操作,進(jìn)行數(shù)值相加操作,最后發(fā)生自動(dòng)裝箱操作轉(zhuǎn)換成Integer對(duì)象。其內(nèi)部變化如下?

sum = sum.intValue() + i;

Integer sum = new Integer(result);?

sum為Integer類(lèi)型,在上面的循環(huán)中會(huì)創(chuàng)建4000個(gè)無(wú)用的Integer對(duì)象,在這樣龐大的循環(huán)中,會(huì)降低程序的性能并且加重了垃圾回收的工作量。因此在我們編程時(shí),需要注意到這一點(diǎn),正確地聲明變量類(lèi)型,避免因?yàn)樽詣?dòng)裝箱引起的性能問(wèn)題?

再舉一個(gè)例子,在Java中的HashMap的性能也受到自動(dòng)拆裝箱的影響 因?yàn)镠ashMap接收的參數(shù)類(lèi)型是HashMap <Object, Object>,所以在增刪改查的時(shí)候,都會(huì)對(duì)Key值進(jìn)行大量的自動(dòng)拆裝箱,為了解決這個(gè)問(wèn)題,Java提供了SparseArray,包括SparseBoolMap, SparseIntMap, SparseLongMap, LongSparseMap,所接受的Key值都是基本類(lèi)型的值,例如SparseIntMap就是SparseIntMap<int, Object>,在避免了大量自動(dòng)拆裝箱的同時(shí),還降低的內(nèi)存消耗。這里就點(diǎn)到為止,具體的數(shù)據(jù)結(jié)構(gòu)的問(wèn)題我們就不深入了?

2. 重載與自動(dòng)裝箱?

在Java5之前,value(int i)和value(Integer o)是完全不相同的方法,開(kāi)發(fā)者不會(huì)因?yàn)閭魅胧莍nt還是Integer調(diào)用哪個(gè)方法困惑,但是由于自動(dòng)裝箱和拆箱的引入,處理重載方法時(shí)稍微有點(diǎn)復(fù)雜,例如在ArrayList中,有remove(int index)和remove(Object o)兩個(gè)重載方法,如果集合持有三個(gè)Integer類(lèi)型值為3,1,2的對(duì)象,我們調(diào)用remove(3), 是調(diào)用了remove的哪個(gè)重載方法?remove掉的是值為3的對(duì)象,還是remove了index為3,值為2的那個(gè)對(duì)象呢?其實(shí)問(wèn)題就是,參數(shù)3是否會(huì)被自動(dòng)打包呢?答案是:不會(huì),在這種情況下,編譯器不會(huì)進(jìn)行自動(dòng)拆裝箱,所以調(diào)用的是remove(int index),index為3值為2的這個(gè)Integer對(duì)象會(huì)被remove?

通過(guò)以下例子我們可以驗(yàn)證?

public void testAutoBoxing(int i){

? ? System.out.println("primitive argument");

?

}

?

public void testAutoBoxing(Integer integer){

? ? System.out.println("wrapper argument");

?

}

?

//calling overloaded method

int value = 1;

test(value); //no autoboxing?

Integer iValue = value;

test(iValue); //no autoboxing

?

Output:

primitive argument

wrapper argument?

3. 緩存值問(wèn)題?

4. 警惕NullPointerException?

我們?cè)谑褂没绢?lèi)型的時(shí)候,在聲明的時(shí)候即使我們沒(méi)有對(duì)變量進(jìn)行賦值,編譯器也會(huì)自動(dòng)的為其賦予初始值,比如int值就是0,boolean就是flase,所以我們?cè)谑褂没绢?lèi)型的時(shí)候,是不會(huì)出現(xiàn)NullPointerException的,但在使用包裝類(lèi)的時(shí)候,我們就要注意這個(gè)問(wèn)題了,不能因?yàn)橛凶詣?dòng)拆裝箱這個(gè)語(yǔ)法糖,就忘記了包裝類(lèi)和基本類(lèi)型的區(qū)別,將其同等對(duì)待了,如果你沒(méi)有在使用包裝類(lèi)的時(shí)候通過(guò)顯式、或是通過(guò)自動(dòng)裝箱機(jī)制為其賦值,在你取出值、或是通過(guò)自動(dòng)拆箱使用該值的時(shí)候,就會(huì)發(fā)生NullPointerException,這個(gè)是大家要注意的?

?鏈接:https://www.jianshu.com/p/547b36f04239? ? https://www.jianshu.com/p/547b36f04239

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的[转载] 什么是Java中的自动拆装箱 integer的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。