包裹基本型態


Java中有兩個型態系統,基本型態與類別型態,使用基本型態目的在於效率,然而更多時候,會使用類別建立實例,因為物件本身可以攜帶更多資訊,如果要讓基本型態像物件一樣操作,可以使用Long、Integer、Double、Float、Boolean、Byte等類別來包裹(Wrap)基本型態。

Long、Integer、Double、Float、Boolean等類別是所謂的包裹器(Wrapper),正如此名稱所示,這些類別主要目的,就是提供物件實例作為「殼」,將基本型態包裹在物件之中,如此就可以操作這個物件,就像是將基本型態當作物件操作。來看個簡單的例子:

package cc.openhome;

public class IntegerDemo {
    public static void main(String[] args) {
        int data1 = 10;
        int data2 = 20;
        
        Integer wrapper1 = new Integer(data1);
        Integer wrapper2 = new Integer(data2);
        
        System.out.println(data1 / 3);
        System.out.println(wrapper1.doubleValue() / 3);
        System.out.println(wrapper1.compareTo(wrapper2));
    }
} 

基本型態包裹器都是歸類於java.lang套件中,如果要使用Integer包裹int型態資料,方法之一是用new建構Integer實例時,傳入int型態資料。型態轉換 中提過,如果運算式中都是int,就只會在int空間中作運算,結果會是int整數,因此data1 / 3就會顯示3的結果。你可以操作IntegerdoubleValue()將包裹值以double型態傳回,如此就會在double空間中作相除,結果就會顯示3.33333333333...。

Integer提供compareTo()方法,可與另一個Integer物件進行比較,如果包裹值相同就傳回0,小於compareTo()傳入物件包裹值就傳回-1,否則就是1,與==!=只能比較是否相等或不相等,compareTo()方法傳回更多資訊。


自動裝箱

除了使用new建構基本型態包裹器之外,從J2SE 5.0之後提供了自動裝箱(Auto boxing)功能,可以如下包裹基本型態:

Integer number = 10;


編譯器會自動判斷是否能進行自動裝箱,在上例中你的number會參考Integer實例;同樣的動作可適用於boolean、byte、short、char、long、float、double等基本型態,分別會使用對應的Boolean、Byte、Short、Character、Integer、Long、Float或Double包裹基本型態。若使用自動裝箱功能來改寫一下IntegerDemo中的程式碼:

Integer data1 = 10;
Integer data2 = 20;
System.out.println(data1.doubleValue() / 3);
System.out.println(data1.compareTo(data2));

程式看來簡潔許多,data1data2在運行時會參考Integer實例,可以直接進行物件操作。自動裝箱運用的方法還可以如下:

int number = 10;
Integer wrapper = number;


自動拆箱

J2SE 5.0後可以自動裝箱,也可以自動拆箱(Auto unboxing),也就是自動取出包裹器中的基本形態資訊。例如:

Integer wrapper = 10;  // 自動裝箱
int foo = wrapper;      // 自動拆箱

wrapper會參考至Integer,若被指定給int型的變數foo,則會自動取得包裹的int型態再指定給foo

在運算時,也可以進行自動裝箱與拆箱,例如:

Integer number = 10;
System.out.println(number + 10);
System.out.println(number++);


上例中會顯示20與10,編譯器會自動自動裝箱與拆箱,也就是10會先裝箱,然後在number + 10時會先對number拆箱,再進行加法運算;number++該行也是先對i拆箱再進行遞增運算。再來看一個例子:

Boolean foo = true;
System.out.println(foo && false);

同樣地,foo會參考至Boolean實例,在進行&&運算時,會先將foo拆箱,再與false進行&&運算,結果會顯示false