[JAVA] Java面向對象之包裝類,拆箱、裝箱

Java面向對象之包裝類,拆箱、裝箱

包裝類,拆箱、裝箱——一切皆對象

爲何要包裝類

  1. 在面向對象中,”一切皆對象”,但基本數據類型的特殊存在不太符合這一理念,面向對象面向得並不純粹,因爲基本類型變量並不是對象;
  2. 涉及進制間的轉換的算法,數據類型間的基本操作;如果都要我們來實現,那工作量就太大了;
  3. Java的集合框架並不支持基本數據類型的存儲,只支持對象存儲;

故此,針對Java基本數據類型封裝了包裝類,每一個基本類型都有一個對應的包裝類,以下是詳情:

基本數據類型的包裝類

八大基本數據類型的包裝類都使用final修飾,都是最終類,都不能被繼承。

// Byte

public final class Byte extends Number implements Comparable<Byte> { }

// Character

public final class Character implements java.io.Serializable, Comparable<Character> { }

// Short

public final class Short extends Number implements Comparable<Short> { }

// Integer

public final class Integer extends Number implements Comparable<Integer> { }

// Long

public final class Long extends Number implements Comparable<Long> { }

// Float

public final class Float extends Number implements Comparable<Float> { }

// Double

public final class Double extends Number implements Comparable<Double> { }

// Boolean

public final class Boolean implements java.io.Serializable, Comparable<Boolean> { }

拆箱和裝箱

裝箱:把基本類型數據轉成對應的包裝類對象。

方式一:


Integer i = Integer.value(13);

方式二:


Integer i = new Integer(13);

拆箱:把包裝類對象轉成對應的基本數據類型數據。


int value = i.intValue();

自動裝箱(Autoboxing)和自動拆箱(AutoUnboxing)

在Java 5之前的版本中,基本數據類型和包裝類之間的轉換是需要手動進行的,但Sun公司從Java5開始提供了的自動裝箱(Autoboxing)和自動拆箱(AutoUnboxing)操作 ;

  • 自動裝箱:可以把一個基本類型變量直接賦給對應的包裝類型變量。

Integer i = 13;
  • 自動拆箱:允許把包裝類對象直接賦給對應的基本數據類型變量。

Integer i = new Integer(13);

Int j = i;

自動裝箱和自動拆箱,也是一個語法糖/編譯器級別新特性,在底層依然是手動裝箱、拆箱操作;但是在裝箱操作中使用的是Integer.valueOf()方法,而不是直接new Integer();其他的幾個包裝類也是如此,裝箱操作中使用的是各自的valueOf()方法。

自動裝箱和自動拆箱的反編譯效果

switch 對包裝類的支持

switch支持的基本數據類型:byte,short,char,int;也支持對應的包裝類。因爲在底層,switch中會對包裝類做手動拆箱操作。

switch 中包裝類的支持

考慮下面的語句:


Object obj = 17;

在上述代碼語句中有如下的操作:

  1. 自動裝箱: Integer i = 17;
  2. 引用的自動類型轉換,把子類對象賦給父類變量: Object obj = i; 因爲Object類的父類;

因此,Object可以接受一切數據類型的值;Object數組:Object[]該數組可以裝一切數據類型。


Object\[\] arr = {“A”,12,3.14,true}; // 這是完全可行的

包裝類的常用操作方法(以Integer爲例):

1. 包裝類中的常量:

  • MAX_VALUE :最大值
  • MIN_VALUE :最小值
  • SIZE :變量在內存中存儲數據佔多少位
  • TYPE :對應的基本類型

2. 包裝類的構造器:創建包裝類對象,

/\*\* Integer 構造器源碼 \*\*/

// 接收int類型數據構建Integer對象

public Integer(int value) {

this.value = value;

}

// 接受字符串數據構建Integer對象

public Integer(String s) throws NumberFormatException {

this.value = parseInt(s, 10);

}

其他的幾個包裝類型也是這樣的規律,具體實現查看源碼即可。

3. 基本類型和包裝類型的轉換(裝箱和拆箱)

裝箱:


Integer i1 = new Integer(13); // 方式一,每次都會創建新對象,不推薦

Integer i2 = Integer.valueOf(13); // 方式二,推薦,底層使用了緩存。

拆箱:


int val = i1.intValue();

4. String和基本類型/包裝類型之間的轉換操作

把String轉換爲包裝類類型:


方式1:包裝類.valueOf(String str):

Integer i = Integer.valueOf(“13”);


方式2: new 包裝類(String str):

Integer i= new Integer(“13”);

把包裝類對象轉換爲String.


String str = 對象.toString(); // 不止包裝類對象,其他任何對象都可以使用toString()轉換;

把基本數據類型轉換爲String:


String str = 13 + "";

把String轉換爲基本數據類型:


parseXxx(String s) : xxx表示8大基本數據類型,如:

String input=”12345”;

int value = Integer.parseInt(input);

5. 對於Boolean來說,無論是使用new Boolean(“”); 還是Boolean.valueOf(“”), 只有使用true/TRUE會被認爲是true,其他都是false。


Boolean b1 = new Boolean("true"); // true

Boolean b1 = new Boolean("TRUE"); // true

Boolean b1 = new Boolean("sjsj"); // false

包裝類中的緩存設計

在包裝類中提供了緩存設計,會對一定範圍內的數據作緩存,如果數據在範圍內,會優先從緩存中取數據,超出範圍纔會創建新對象;Byte、Short、Integer、Long:緩存[-128,127]區間的數據;Character:緩存[0,127]區間的數據;包裝類中的緩存設計,也稱爲享元模式。

緩存設計會在包裝類中的valueOf()方法中實現,所以纔會推薦使用valueOf()方法來實現拆箱操作,如下是Integer類的valueOf()源碼:

valueOf()

再查看緩存實現細節:

IntegerCache

通過查看源碼可知,JVM會對-128 到 127之間的做緩存,如果你的變量值在這個範圍內,就會優先從緩存中取數據,否則就會創建新對象。當然這個緩存區間也是可是設置的。

那麼以下這個例子就可以解釋了:

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

    Integer i1 = Integer.valueOf(13);
    Integer i2 = Integer.valueOf(13);

    System.out.println(i1 == i2);
    // 輸出爲true。因爲13在\[-128, 127\]之間,但是並沒有創建新對象

    Integer i3 = Integer.valueOf(129);
    Integer i4 = Integer.valueOf(129);

    System.out.println(i3 == i4);
    // 輸出爲false, 因爲129不在\[-128, 127\]之間,是使用new Integer()創建了新對象,故比較爲false

    Integer i5 = 129;
    Integer i6 = 129;

    System.out.println(i5 == i6); // 輸出爲false
    System.out.println(i5.equals(i6));

    // 輸出爲true,建議:如果對象包裝類對象的值作比較,應選用包裝類的equals方法。

}

我們再來看Integer的equals方法的實現源碼:

Integer的equals方法

可以發現,包裝類在比較時會將包裝類型拆箱爲基本數據類型,並使用==做比較。

包裝類型和基本數據類型的區別

包裝類型和基本數據類型的區別(以Integer與int的區別爲例):

1. 默認值:

  • int的默認值是0。
  • Integer的默認值爲null。Integer既可以表示null,又可以表示0。

2. 包裝類中提供了該類型相關的很多算法操作方法:

*   static String toBinaryString(int i) :把十進制轉換爲二進制
*   static String toOctalString(int i) : :把十進制轉換爲八進制
*   static String toHexString(int i) : :把十進制轉換爲十六進制

3. 在集合框架中,只能存儲對象類型,不能存儲基本數據類型值。

4. Integer和int並不是相同的數據類型,儘管值是相同的。Integer是一個類,可以實例化爲對象,但int只是一個基本數據類型。

5. 在JVM中,基本類型變量存儲在棧中的,而包裝類型對象存放於堆中。

其實,包裝類就是把基本數據類對象化,包裝類是基本數據類型的超集;在開發中,建議成員變量優先使用包裝類型,局部變量優先考慮基本數據類型。

完結。老夫雖不正經,但老夫一身的才華

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章