1. 導論
在 Java 語言中存在兩大類資料。第一類是基本型別:int、char、double、boolean 等。它們簡單且快速:值直接存放在記憶體的儲存格中。第二類是參考型別,也就是物件:變數儲存的是指向物件在記憶體中位置的參考。
有時需要把基本型別當作物件來使用,但基本型別本身不是物件。這種情況下會用到特殊的 包裝類。
包裝類是把基本值包在類別之中的類,讓你能把它當作物件操作。例如,對於 int — 類別 Integer,對於 double — Double,對於 char — Character,對於 boolean — Boolean。這些類別提供方法:Integer.parseInt()、Double.isInfinite()、Character.isLetter()、Boolean.parseBoolean() 等。
從 Integer 物件取得自 int 基本值的範例:
// 基本型別
int a = 10;
// 包裝物件
Integer b = Integer.valueOf(10);
變數 a 儲存的是數值 10。而變數 b 儲存的是一個物件的參考,該物件內部包含 10。
2. 為什麼需要包裝類
基本型別永遠是具體的值,不能設為 null。物件可以不存在並持有空值——當需要表示「未知」或「缺席」時很方便。
基本型別沒有方法。不能對數字呼叫像 x.toString() 之類的東西。包裝類提供這些能力:Integer.parseInt("123") 會把字串轉成數字,而數字也可以透過 toString() 轉成字串。
總結:在需要物件的地方就需要包裝類——例如要能儲存 null、呼叫方法、或把值傳給只接受物件的 API(例如 List<Integer> 這類集合)。
包裝類型完整清單
| 基本型別 | 包裝類 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3. 裝箱與拆箱
當你手動建立包裝物件時,你會把基本值「裝箱」到物件裡:
int primitive = 42;
Integer wrapper = Integer.valueOf(primitive); // 裝箱
若要取回基本值——「拆箱」——可以使用例如 intValue():
Integer wrapper = Integer.valueOf(42);
int primitive = wrapper.intValue(); // 拆箱
自動裝箱 (Autoboxing)
當你把基本型別指定給包裝類變數時,編譯器會自動補上 valueOf() 呼叫:
int a = 10;
Integer b = a; // 自動裝箱 (Integer.valueOf(a))
自動拆箱 (Unboxing)
反過來——當在需要基本型別的地方使用包裝物件時:
Integer c = 20;
int d = c; // 自動拆箱 (c.intValue())
int a = 10; // 基本型別
Integer b = a; // 自動裝箱
Integer c = Integer.valueOf(20);
int d = c; // 自動拆箱
4. 潛在陷阱
包裝類的比較。 運算子 == 對物件比較的是參考,而不是值:
Integer m = 200;
Integer n = 200;
System.out.println(m == n); // false, 因為它們是不同的物件
Java 會快取數值位於 -128 到 127 範圍內的包裝物件,因此有時 == 會回傳 true,有時則是 false。要比較值時請一律使用 equals():
Integer x = 100;
Integer y = 100;
System.out.println(x == y); // true, 命中快取
System.out.println(x.equals(y)); // true, 按值比較
自動拆箱時的 NullPointerException。 若包裝物件為 null,而你嘗試拆箱——就會丟出例外:
Integer value = null;
int primitive = value; // 錯誤! NullPointerException
效能與記憶體。 包裝類比基本型別慢且佔用更多記憶體。在熱點程式碼與需要處理大型數值陣列時,請選擇基本型別。
5. 範例
Integer 與 Double 的範例
將字串轉為數字:
String text = "123";
int number = Integer.parseInt(text);
System.out.println(number); // 123
檢查浮點數的特殊值:
double d = 1.0 / 0;
System.out.println(Double.isInfinite(d)); // true
double nan = 0.0 / 0.0;
System.out.println(Double.isNaN(nan)); // true
Character 的範例
char 儲存單一字元;包裝類 Character 提供便利的檢查:
char ch = 'A';
Character wrapper = ch; // 自動裝箱
System.out.println(Character.isLetter(ch)); // true
System.out.println(Character.isDigit(ch)); // false
System.out.println(Character.toLowerCase(ch)); // 'a'
Boolean 的範例
基本型別 boolean 只有 true/false。包裝類 Boolean 還可以儲存 null:
Boolean flag = null; // 允許
flag = Boolean.TRUE; // 特殊常數
System.out.println(flag); // true
將字串轉為布林值:
String s1 = "true";
String s2 = "false";
boolean b1 = Boolean.parseBoolean(s1);
boolean b2 = Boolean.parseBoolean(s2);
System.out.println(b1); // true
System.out.println(b2); // false
GO TO FULL VERSION