Java - 基本型別 & 包裝類別
型別
基本型別(Primitive Type)
Data Type | Size | Range | Default |
---|---|---|---|
byte | 1 byte | -128 ~ 127 | 0 |
short | 2 bytes | -32768 ~ 32767 | 0 |
int | 4 bytes | -2^31 ~ 2^31-1 | 0 |
float | 4 bytes | -3.4e38 ~ 3.4e38 | 0.0f |
long | 8 bytes | -2^63 ~ 2^63-1 | 0L |
double | 8 bytes | -1.7e308 ~ 1.7e308 | 0.0d |
boolean | 1 bit | true, false | false |
char | 2 bytes | \u000 ~ \ufff | \u000 |
包裝類別、參考型別(Wrapper Class、Reference Type)
每一個基本型別都有一個對應的包裝類別,如下:
Primitive Type | Wrapper Class |
---|---|
byte | Byte |
short | Short |
int | Integer |
float | Float |
long | Long |
double | Double |
boolean | Boolean |
char | Character |
除了 Boolean、Character 以外,其他的包裝類別皆繼承 Number 類,而最上層的類別即 Object。
也因為全部都是繼承 Object,所以其底下的所有包裝類別皆可實作 Object 裡面的功能,如: hashCode()、toString()、equals()…等等。
因為 objects 本身是 reference type,所以它們的 default value 為 null,而 primitive type 的值不能是 null,所以若你宣告了一個 primitive type 的變數而沒有賦值,則系統會給他預設的值,如表 1。
包裝類別還有一個特點,就是可以將字串轉成特定的資料型態,如: Integer 類別裡面的 parseInt(將字串轉成整數類別)。
Boxing & Unboxing
名詞解釋
-
裝箱(boxing): 是指將基本類別轉為對應的包裝類別(Wrapper Object),如: int 轉為 Integer。
-
拆箱(unboxing): 即裝箱的反意,將包裝類別轉為對應的基本類別,如: Float 轉為 float。
-
自動裝箱(autoboxing): 是指 Java 編譯器自動將基本類別轉為對應的包裝類別。
程式範例
// Autoboxing
Integer foo1 = 100;
// Auto-unboxing
int foo2 = foo1;
ArrayList<Integer> fooArr = new ArrayList<Integer>();
// 加入基本類型的值,java 會自動做 boxing 的動作(Autoboxing)
fooArr.add(1);
fooArr.add(2);
Autoboxing & Unboxing 效能問題
請看以下範例,試想該範例有什麼問題
public class Foo {
private static Integer sum = 0;
public static void main(String... args) {
for (int i = 1; i <= 10; i++) {
sum = sum + i;
}
}
}
解析此範例程式的流程:
- sum 是 Integer(Wrapper Type),所以在計算前會先 unbox 成 int
- sum + i 得到新的 int 值
- 新的 int 值要 assgin 回去給 sum,但發現 sum 是 wrapper type,所以又建立了一個新的 Integer obj
看了上面的流程解析可以發現,此迴圈總共會跑 10 次,並建立 10 個不同的 Object,且這些 Object 都需要做 GC(Garbage Collection),如果迴圈不只 10 次,那對於專案的效能影響是非常大的。
在 Javadocs 有提到 autoboxing 和 unboxing 只適合用於你必須在 Collection 裡面放入數字的值,並不適用於計算上。