Kurt/Java - 基本型別 & 包裝類別

Created Mon, 21 Feb 2022 22:23:56 +0800 Modified Wed, 02 Nov 2022 05:33:26 +0000
885 Words 4 min

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;
        }
    }
}

解析此範例程式的流程:

  1. sum 是 Integer(Wrapper Type),所以在計算前會先 unbox 成 int
  2. sum + i 得到新的 int 值
  3. 新的 int 值要 assgin 回去給 sum,但發現 sum 是 wrapper type,所以又建立了一個新的 Integer obj

看了上面的流程解析可以發現,此迴圈總共會跑 10 次,並建立 10 個不同的 Object,且這些 Object 都需要做 GC(Garbage Collection),如果迴圈不只 10 次,那對於專案的效能影響是非常大的。

在 Javadocs 有提到 autoboxing 和 unboxing 只適合用於你必須在 Collection 裡面放入數字的值,並不適用於計算上。