概述
本文中小編爲大家細緻的講解了Java中基本數據類型對應的包裝類以及包裝類的緩衝機制在實際開發中的應用 。 並且對Java中基本數據類型的包裝類的主要應用---自動封箱、自動拆箱做了底層剖析 。
自JDK1.5開始, 引入了自動裝箱/拆箱這一語法糖, 它使程序員的代碼變得更加簡潔, 不再需要進行顯式轉換。基本類型與包裝類型在某些操作符的作用下, 包裝類型調用valueOf()方法將原始類型值轉換成對應的包裝類對象的過程, 稱之爲自動裝箱; 反之調用xxxValue()方法將包裝類對象轉換成原始類型值的過程, 則稱之爲自動拆箱。
一、Java中基本數據類型各自對應的包裝類
詳細的數據類型學習請參閱:數據類型總結
二、Jav中包裝類的實際應用
封箱 :
Integer in = new Integer(123); //將一個基本數據類型的值轉換爲對應的引用類型的對象。
System.out.println(in);//打印出的是對象的值,而不是地址 --- 底層對toString做過重寫
注意:
字符串轉Integer :
Integer in = new Integer("0x23"); //運行報錯:字符串底層是以字符串數組形式存儲,在轉換時會一次判斷每一位是不是數字,所以只支持十進制的數。
數值型的基本數據類型的包裝類都是Number類的子類。
字符串轉Boolean:
Boolean b = new Boolean(str); //要求參數是字符串,當str="true"時 b值爲 true;當str爲"false"或任意字符串時,b值爲false。
自動封箱:
將一個基本數據類型的變量直接賦值給對應引用類型。是JDK1.5的新特性 之一。
底層實現:自動封箱實際上是調用了靜態方法valueOf() --> Integer in = Integer.valueOf(i); valueOf返回一個Integer類型的實例。或者是類似於上面的自動調用Integer的構造方法實現自動封箱,Integer in = 1。
/*
* 自動封箱的測試
*/
int i = 1;
int j = 1;
Integer in1 = i;//自動封箱
Integer in2 = Integer.valueOf(i);
System.out.println(in1==in2);//true
System.out.println(in1.equals(in2));//true
System.out.println(in1.equals(j));//true
//j是一個基本數據類型,在用equals方法進行對象的比較時,j被自動封箱
自動拆箱:
int num1 = 1;
int num2 = 2;
Integer in = num1;
int res = in+num2;//拆箱
System.out.println(res);
//將一個引用類型的實例直接賦值給對應基本數據類型的變量。 JDK1.5的新特性之一。底層實現:實際上是調用了****value()方法(xxx指的是對應 的基本數據類型)。---> int i = in.intVlaue(); // ***value() 返回對應基本類型的值。
整數的哈希碼是自己本身。Integer底層對hashCode()方法做過重寫。
數值類型的哈希碼是不變的。
注意:
Integer i1 = 123;
Integer i2 = 123;
i1==i2 ;//true;
Integer i3 = 1234;
Integer i4 = 1234;
i3==i4;//false
解釋:int類型的值在常量池中初始化,只初始化-128~127的範圍。所以當值在-128~127中時,是直接從從常量池中取值,而常量池中的常量是被共享的,所以i1==i2;當值 不在-128~127之間時,會new Integer(),所以i3、i4指向的堆內存地址 不一樣。
自動拆箱應用:
Integer i1 = new Ingeter(123);
int i = 123;
i1 == i; //true
解釋: 當引用類型與基本類型直接運算時,引用類型會自動拆箱。
底層的原理:自動調用了intValue()來實現拆箱。其他類型類推。
三、包裝類的緩衝機制
- 包裝類同String類相似,也是非可變類,其對象一經創建,就不能修改。並且,包裝類也重寫了equals方法,對於相同類型的兩個包裝類對象,只要兩個對象所包裝的基本數據類型的值是相等的,則equals方法就會返回true,否則返回false。
- 在使用“==”比較兩個包裝類引用時,如果兩個引用指向的地址相同(指向相同的對象),則結果爲true,否則結果爲false。
- 包裝類提供了對象的緩存,具體的實現方式爲在類中預先創建頻繁使用的包裝類對象,當需要使用某個包裝類的對象時,如果該對象封裝的值在緩存的範圍內,就返回緩存的對象,否則創建新的對象並返回。
在包裝類中,緩存的基本數據類型值得範圍如下:
包裝類型 | 基本數據類型 | 緩存對象(基本數據類型值) |
---|---|---|
Boolean | boolean | true,false(全部值) |
Byte | byte | -128~127(全部值) |
Short | short | -128~127 |
Character | char | 0~127 |
Integer | int | -128~127(默認爲127) |
Long | long | -128~127 |
Float | float | 無緩存值 |
Double | double | 無緩存值 |
在jdk1.5及之後的版本中,Java在5大包裝類中(Byte,Charactor,Short,Integer,Long)增加了相應的私有靜態成員內部類爲相應包裝類對象提供緩存機制,Integer包裝類的內部緩存類源碼如下:
正如源碼中所指,在自動裝箱的基礎上,緩存機制纔會發生作用;當包裝類加載時,內部類會初始化一個長度爲((high-low)+1)的包裝類類型數組,low有固定值爲-128,而high的默認值爲127,還可以通過系統配置文件進行修改,自定義high的取值範圍是127---------(Interger.MAX_VALUE+127),Integer.MAX_VALUE是int類型變量的最大正數取值;’
其緩存機制是:當通過自動裝箱機制創建包裝類對象時,首先會判斷數值是否在-128----127的範圍內,如果滿足條件,則會從緩存中尋找指定數值,若找到緩存,則不會新建對象,只是指向指定數值對應的包裝類對象,否則,新建對象。
Integer a = new Integer(100);
Integer b = new Integer(100);
System.out.println(a == b);
// 輸出爲false,非自動裝箱機制實現,屬於兩個不同的對象,所以返回false.
//--------------------------------分割線---------------------------------------
int num1 = 127;
int num2 = 127;//
Integer in1 = num1;
Integer in2 = num2;
System.out.println(in1 == in2);//true
//全部都在範圍之內,所以爲true
//--------------------------------分割線---------------------------------------
int num3 = 127;
int num4 = 128;//超過了上限,成爲一個緩衝範圍外的新對象
Integer in3 = num3;
Integer in4 = num4;
System.out.println(in3 == in4);//false
//num4的包裝類in4超過了上限,成爲一個緩衝範圍外的新對象,所以爲false
其實,Integer的緩存下限固定爲-128,而緩存上限是可以在運行時通過修改系統屬性來設置的。
比如可以在命令行輸入:
java -Djava.lang.Integer.IntegerCache.high=100 xxx
或者在選擇server虛擬機時,輸入:
java -server -XX:AutoBoxCacheMax=100 xxx
如果去掉-server參數,將報錯,這是因爲,默認的虛擬機是client虛擬機,也就是不加參數或者使用-client參數時系統選擇的虛擬機,而client虛擬機不支持-XX:AutoBoxCacheMax參數。
如果同時使用以上方式來設置緩存上限屬性,以-XX:AutoBoxCacheMax參數爲準。
後記
感謝各位大神的閱讀 , 如果有錯誤的地方或者是文章剖析的不夠透徹 , 希望您能夠不吝賜教在評論中告訴小編 , 以便小編能 更好的提升文章的質量。如果您還有什麼不明白的地方也可以在評論中與大家一起探討。
每個人都是自己的上帝。如果你自己都放棄自己了,還有誰會救你?------《肖申克的救贖》