Wrap包裹

1.用Integer物件包裹int

public class WrapperDemo { public static void main(String[] args) { int data1 = 10; int data2 = 20;

    // 使用Integer來包裏int資料
    Integer data1Wrapper = new Integer(data1);
    Integer data2Wrapper = new Integer(data2);

    // 直接除以3
    System.out.println(data1 / 3);

    // 轉為double值再除以3
    System.out.println(data1Wrapper.doubleValue() / 3);

    // 進行兩個值的比較
    System.out.println(data1Wrapper.compareTo(data2Wrapper));
}

}

compareTo() 可以直接比較與另一個 Integer 物件是否相等,如果是就傳回 0,比指定值小的話傳回 -1,比指定值大的話傳回 1,與使用 '==' 只能比較是否相同,compareTo() 方法傳回更多的資訊

可改寫

在 J2SE 5.0 之後提供了自動裝箱的功能,您可以直接如下撰寫來包裹基本型態:

Integer integer = 10;

您也可以使用更一般化的 java.lang.Number 類別來自動裝箱,例如:

Number number = 3.14f;

3.14f 會先被自動裝箱為 Float,然後指定給 number。

J2SE 5.0 中可以自動裝箱,也可以自動拆箱(unboxing),也就是將物件中的基本形態資訊從物件中自動取出,例如下面這樣寫是可以的:

Integer fooInteger = 10; int fooPrimitive = fooInteger;

fooInteger 參考至自動裝箱為 Integer 的實例後,如果被指定給一個 int 型態的變數 fooPrimitive,則會自動變為 int 型態再指定給 fooPrimitive;在運算時,也可以進行自動裝箱與拆箱,例如:

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

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

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

同樣的 boo 原來是 Boolean 的實例,在進行 AND 運算時,會先將 boo 拆箱,再與 false 進行 AND 運算,結果會顯示 false。

自動裝箱必須要注意的地方

自動裝箱與拆箱的功能是所謂的「編譯器蜜糖」(Compiler sugar),雖然使用這個功能很方便,但在程式運行階段您還是瞭解 Java 的語義,例如下面的程式是可以通過編譯的:

Integer i = null; int j = i;

這樣的語法在編譯時期是合法的,但是在運行時期會有錯誤,因為這種寫法相當於:

Integer i = null; int j = i.intValue();

null 表示 i 沒有參考至任何的物件實體,它可以合法的指定給物件參考名稱,由於實際上 i 並沒有參考至任何的物件,所以也就不可能操作 intValue() 方法,所以上面的寫法在運行時會出現 NullPointerException 的錯誤。

自動裝箱、拆箱的功能提供了方便性,但隱藏了一些細節,所以必須小心,再來看範例 4.6,您以為結果是如何? 範例 4.6 AutoBoxDemo2.java

public class AutoBoxDemo2 { public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100;

    if (i1 == i2) 
        System.out.println("i1 == i2");
    else 
        System.out.println("i1 != i2");
}

}

以自動裝箱與拆箱的機制來看,您可能會覺得結果是顯示 "i1 == i2",您是對的!那麼範例 4.7 的這個程式,您覺得結果是什麼? 範例 4.7 AutoBoxDemo3.java

public class AutoBoxDemo3 { public static void main(String[] args) { Integer i1 = 200; Integer i2 = 200;

    if (i1 == i2) 
        System.out.println("i1 == i2");
    else 
        System.out.println("i1 != i2");
}

}

結果是顯示 "i1 != i2",這有些令人訝異,兩個範例語法完全一樣,只不過改個數值而已,結果卻相反。

其實這與 '==' 運算子的比較有關,在第 3 章中介紹過 '==' 是用來比較兩個基本型態的變數值是否相等,事實上 '==' 也用於判斷兩個物件參考名稱是否參考至同一個物件。

在自動裝箱時對於值從 -128 到 127 之間的值,它們被裝箱為 Integer 物件後,會存在記憶體之中被重用,所以範例 4.6 中使用 '==' 進行比較時,i1 與 i2 實際上參考至同一個物件,如果超過了從 -128 到 127 之間的值,被裝箱後的 Integer 物件並不會被重用,即相當於每次裝箱時都新建一個 Integer 物件,所以範例 4.7 使用 '==' 進行比較時,i1 與 i2 參考的是不同的物件。

所以不要過份依賴自動裝箱與拆箱,您還是必須知道基本型態與物件的差異,範例 4.7 最好還是依正規的方式來寫,而不是依賴編譯器蜜糖(Compiler sugar),例如範例 4.7 必須改寫為範例 4.8 才是正確的。 範例 4.8 AutoBoxDemo4.java

public class AutoBoxDemo4 { public static void main(String[] args) { Integer i1 = 200; Integer i2 = 200;

    if (i1.equals(i2)) 
        System.out.println("i1 == i2");
    else 
        System.out.println("i1 != i2");
}

}

結果這次是顯示 "i1 == i2" 了,使用這樣的寫法,相信您也會比較放心一些,對於這些方便但隱藏細節的功能到底要不要用呢?基本上只有一個原則:如果您不確定就不要用。

results matching ""

    No results matching ""