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

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

生活随笔

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

java

java中为什么设计包装类,Java 中为什么要设计包装类

發(fā)布時(shí)間:2023/12/20 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java中为什么设计包装类,Java 中为什么要设计包装类 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

最近文章更新頻率慢了,因?yàn)樽罱跍?zhǔn)備暑期實(shí)習(xí),之前尋思著一邊復(fù)習(xí)一邊寫(xiě)文章,兩全其美。后來(lái)發(fā)現(xiàn)一篇讀起來(lái)比較舒服的文章寫(xiě)出來(lái)加上配圖得花上四五個(gè)小時(shí)甚至更多,但這個(gè)知識(shí)點(diǎn)我可能半個(gè)小時(shí)就能復(fù)習(xí)完了,春招在即,時(shí)間比較緊迫,所以最近文章可能改為一周一更或者一周兩更,希望各位理解。另外,有和我一樣在準(zhǔn)備暑期實(shí)習(xí)的小伙伴可以聯(lián)系我互相交流

全文脈絡(luò)思維導(dǎo)圖如下:

1. 為什么需要包裝類(lèi)

在 Java 中,萬(wàn)物皆對(duì)象,所有的操作都要求用對(duì)象的形式進(jìn)行描述。但是 Java 中除了對(duì)象(引用類(lèi)型)還有八大基本類(lèi)型,它們不是對(duì)象。那么,為了把基本類(lèi)型轉(zhuǎn)換成對(duì)象,最簡(jiǎn)單的做法就是將基本類(lèi)型作為一個(gè)類(lèi)的屬性保存起來(lái),也就是把基本數(shù)據(jù)類(lèi)型包裝一下,這也就是包裝類(lèi)的由來(lái)。

這樣,我們先自己實(shí)現(xiàn)一個(gè)簡(jiǎn)單的包裝類(lèi),以包裝基本類(lèi)型?int?為例://?包裝類(lèi)?MyInt

public?class?MyInt?{

private?int?number;?//?基本數(shù)據(jù)類(lèi)型

public?Int?(int?number){?//?構(gòu)造函數(shù),傳入基本數(shù)據(jù)類(lèi)型

this.number?=?number;

}

public?int?intValue(){?//?取得包裝類(lèi)中的數(shù)據(jù)

return?this.number;

}

}

測(cè)試一下這個(gè)包裝類(lèi):public?static?void?main(String[]?args)?{

MyInt?temp?=?new?Int(100);?//?100?是基本數(shù)據(jù)類(lèi)型,?將基本數(shù)據(jù)類(lèi)型包裝后成為對(duì)象

int?result?=?temp.intValue();?//?從對(duì)象中取得基本數(shù)據(jù)類(lèi)型

System.out.println(result);

}

當(dāng)然,我們自己實(shí)現(xiàn)的這個(gè)包裝類(lèi)非常簡(jiǎn)單,Java 給我們提供了更完善的內(nèi)置包裝類(lèi):基本類(lèi)型對(duì)應(yīng)的包裝類(lèi)(位于 java.lang 包中)byteByte

shortShort

intInteger

longLong

floatFloat

doubleDouble

charCharacter

booleanBoolean

前 6 個(gè)類(lèi)派生于公共的超類(lèi)?Number,而?Character?和?Boolean?是?Object?的直接子類(lèi)。

來(lái)看看包裝類(lèi)的聲明,以?Integer?為例:

被?final?修飾,也就是說(shuō) Java 內(nèi)置的包裝類(lèi)是無(wú)法被繼承的。

2. 裝箱與拆箱

OK,現(xiàn)在我們已經(jīng)知道了,存在基本數(shù)據(jù)類(lèi)型與其對(duì)應(yīng)的包裝類(lèi),那么,他們之間互相的轉(zhuǎn)換操作就稱(chēng)為裝箱與拆箱:裝箱:將基本數(shù)據(jù)類(lèi)型轉(zhuǎn)換成包裝類(lèi)(每個(gè)包裝類(lèi)的構(gòu)造方法都可以接收各自數(shù)據(jù)類(lèi)型的變量)

拆箱:從包裝類(lèi)之中取出被包裝的基本類(lèi)型數(shù)據(jù)(使用包裝類(lèi)的 xxxValue 方法)

下面以?Integer?為例,我們來(lái)看看 Java 內(nèi)置的包裝類(lèi)是如何進(jìn)行拆裝箱的:Integer?obj?=?new?Integer(10);??//?自動(dòng)裝箱

int?temp?=?obj.intValue();??//?自動(dòng)拆箱

可以看出,和上面我們自己寫(xiě)的包裝類(lèi)使用方式基本一樣,事實(shí)上,Integer?中的這兩個(gè)方法其底層實(shí)現(xiàn)和我們上述寫(xiě)的代碼也是差不多的。

不知道各位發(fā)現(xiàn)沒(méi),value?被聲明為?final?了,也就是說(shuō)一旦構(gòu)造了包裝器,就不允許更改包裝在其中的值。

另外,需要注意的是,這種形式的代碼是?JDK 1.5 以前的!!!JDK 1.5 之后,Java 設(shè)計(jì)者為了方便開(kāi)發(fā)提供了自動(dòng)裝箱與自動(dòng)拆箱的機(jī)制,并且可以直接利用包裝類(lèi)的對(duì)象進(jìn)行數(shù)學(xué)計(jì)算。

還是以?Integer?為例我們來(lái)看看自動(dòng)拆裝箱的過(guò)程:Integer?obj?=?10;??//?自動(dòng)裝箱.?基本數(shù)據(jù)類(lèi)型?int?->?包裝類(lèi)?Integer

int?temp?=?obj;??//?自動(dòng)拆箱.?Integer?->?int

obj?++;?//?直接利用包裝類(lèi)的對(duì)象進(jìn)行數(shù)學(xué)計(jì)算

System.out.println(temp?*?obj);

看見(jiàn)沒(méi)有,基本數(shù)據(jù)類(lèi)型到包裝類(lèi)的轉(zhuǎn)換,不需要像上面一樣使用構(gòu)造函數(shù),直接?=?就完事兒;同樣的,包裝類(lèi)到基本數(shù)據(jù)類(lèi)型的轉(zhuǎn)換,也不需要我們手動(dòng)調(diào)用包裝類(lèi)的 xxxValue 方法了,直接?=?就能完成拆箱。這也是將它們稱(chēng)之為自動(dòng)的原因。

我們來(lái)看看這段代碼反編譯后的文件,底層到底是什么原理:Integer?obj?=?Integer.valueOf(10);

int?temp?=?obj.intValue();

可以看見(jiàn),自動(dòng)裝箱的底層原理是調(diào)用了包裝類(lèi)的?valueOf?方法,而自動(dòng)拆箱的底層調(diào)用了包裝類(lèi)的?intValue()?方法。

3. 不簡(jiǎn)單的 Integer.valueOf

我們上面已經(jīng)看過(guò)了用于自動(dòng)拆箱的?intValue?方法的源碼,非常簡(jiǎn)單。接下來(lái)咱來(lái)看看用于自動(dòng)裝箱的?valueOf,其他包裝類(lèi)倒沒(méi)什么好說(shuō)的,不過(guò)?Integer?中的這個(gè)方法還是有點(diǎn)東西的:

IntegerCache?又是啥,點(diǎn)進(jìn)去看看:

IntegerCache?是?Integer?類(lèi)中的靜態(tài)內(nèi)部類(lèi),綜合這兩段代碼,我們大概也能知道,IntegerCache?其實(shí)就是個(gè)緩存,其中定義了一個(gè)緩沖區(qū)?cache,用于存儲(chǔ)?Integer?類(lèi)型的數(shù)據(jù),緩存區(qū)間是 [-128, 127]。

回到?valueOf?的源碼:它首先會(huì)判斷 int 類(lèi)型的實(shí)參 i 是否在可緩存區(qū)間內(nèi),如果在,就直接從緩存?IntegerCache?中獲取對(duì)應(yīng)的?Integer?對(duì)象;如果不在緩存區(qū)間內(nèi),則會(huì) new 一個(gè)新的?Integer?對(duì)象。

結(jié)合這個(gè)特性,我們來(lái)看一個(gè)題目,兩種類(lèi)似的代碼邏輯,但是卻得到完全相反的結(jié)果。:public?static?void?main(String?args[])?{

Integer?a1?=?127;

Integer?a2?=?127;

System.out.println(a1?==?a2);?//?true

Integer?b1?=?128;

Integer?b2?=?128;

System.out.println(b1?==?b2);?//?false

}

我們知道,==?擁有兩種應(yīng)用場(chǎng)景:對(duì)于引用類(lèi)型來(lái)說(shuō),判斷的是內(nèi)存地址是否相等

對(duì)于基本類(lèi)型來(lái)說(shuō),判斷的是值是否相等

從 a1 開(kāi)始看,由于其值在?InterCache?的緩存區(qū)間內(nèi),所以這個(gè)?Integer?對(duì)象會(huì)被存入緩存。而在創(chuàng)建 a2 的時(shí)候,由于其值和 a1 相等,所以直接從緩存中取出值為 127 的?Integer?對(duì)象給 a2 使用,也就是說(shuō),a1 和 a2 這兩個(gè)?Integer?的對(duì)象引用都指向同一個(gè)地址。

對(duì)于 b1 和 b2 來(lái)說(shuō),由于 128 不在?IntegerCache?的緩存區(qū)間內(nèi),那就只能自己老老實(shí)實(shí)開(kāi)辟空間了,所以 b1 和 b2 指向不同的內(nèi)存地址。

很顯然,由于?InterCache?緩存機(jī)制的存在,可能會(huì)讓我們?cè)诰幊痰臅r(shí)候出現(xiàn)困惑,因此最好使用?.equals?方法來(lái)比較?Integer?值是否相等。Integer?重寫(xiě)了?.equals?方法:

當(dāng)然,其他包裝類(lèi)雖然沒(méi)有緩存機(jī)制,但是也都重載了?.equals?方法,用于根據(jù)值來(lái)判斷是否相等。因此,得出結(jié)論,使用?equals?方法來(lái)比較兩個(gè)包裝類(lèi)對(duì)象的值。

4. Object 類(lèi)可以接收所有數(shù)據(jù)類(lèi)型

綜上,有了自動(dòng)拆裝箱機(jī)制,基本數(shù)據(jù)類(lèi)型可以自動(dòng)的被轉(zhuǎn)為包裝類(lèi),而?Object?是所有類(lèi)的父類(lèi),也就是說(shuō),Object?可以接收所有的數(shù)據(jù)類(lèi)型了(引用類(lèi)型、基本類(lèi)型)!!!

不信你可以試試,直接用?Object?類(lèi)接收一個(gè)基本數(shù)據(jù)類(lèi)型?int,完全是可以的。Object?obj?=?10;

int?temp?=?(Integer)?obj;

解釋一下上面這段代碼發(fā)生了什么,下面這張圖很重要,大家仔細(xì)看:

5. 包裝類(lèi)在集合中的廣泛使用

其實(shí)包裝類(lèi)最常見(jiàn)的使用就是在集合中,因?yàn)榧喜辉试S存儲(chǔ)基本類(lèi)型的數(shù)據(jù),只能存儲(chǔ)引用類(lèi)型的數(shù)據(jù)。那如果我們想要存儲(chǔ) 1、2、3 這樣的基本類(lèi)型數(shù)據(jù)怎么辦?舉個(gè)例子,我們可以如下聲明一個(gè)?Integer對(duì)象的數(shù)組列表:ArrayList?list?=?new?ArrayList<>();

往這個(gè)列表中添加?int?型數(shù)據(jù):list.add(3);

上面這個(gè)調(diào)用在底層將會(huì)發(fā)生自動(dòng)裝箱操作:list.add?(Integer.valueOf(3));

基本數(shù)據(jù)類(lèi)型?int?會(huì)被轉(zhuǎn)換成?Integer?對(duì)象存入集合中。

我們?cè)賮?lái)從這個(gè)集合中根據(jù)某個(gè)下標(biāo) i 獲取對(duì)應(yīng)的?Integer?對(duì)象,并用基本數(shù)據(jù)類(lèi)型?int?接收:int?n?=?list.get(i);

上面這個(gè)調(diào)用在底層將會(huì)發(fā)生自動(dòng)拆箱操作:int?n?=?list.get(i).intValue();

6. 數(shù)據(jù)類(lèi)型轉(zhuǎn)換

另外,除了在集合中的廣泛應(yīng)用,包裝類(lèi)還包含一個(gè)重要功能,那就是提供將String型數(shù)據(jù)變?yōu)榛緮?shù)據(jù)類(lèi)型的方法,使用幾個(gè)代表的類(lèi)做說(shuō)明:

Integer:

Double:

Boolean:

這些方法均被?static?標(biāo)識(shí),也就是說(shuō)它們被各自對(duì)應(yīng)的所有對(duì)象共同維護(hù),直接通過(guò)類(lèi)名訪問(wèn)該方法。舉個(gè)例子:String?str?=?"10";

int?temp?=?Integer.parseInt(str);//?String?->?int

System.out.println(temp?*?2);?//?20

需要特別注意的是:Character?類(lèi)里面并不存在字符串變?yōu)樽址姆椒?#xff0c;因?yàn)?String?類(lèi)中已經(jīng)有一個(gè)?charAt()的方法可以根據(jù)索引取出字符內(nèi)容。

總結(jié)

以上是生活随笔為你收集整理的java中为什么设计包装类,Java 中为什么要设计包装类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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