在之前的文章我們介紹了一下 Java 中的Object,本章我們來看一下 Java 中的包裝類。
在 Java 中有八個基本類型:byte,short,int,long,float,double,char,boolean,是以值的形式存在的,所以他們並沒有面向對象的特征,自然也不繼承自 Object,所以不能使用多台,用 Object 的角度去接受基本類型。
假設現在我們有一個計算 1+1 的值,代碼如下:
1 public class Main { 2 public static void main(String[] args) { 3 int i = 1 + 1; 4 System.out.println(i); // 2 5 6 Integer integer1 = new Integer(1); 7 Integer integer2 = new Integer(1); 8 int integer = integer1.intValue() + integer2.intValue(); 9 System.out.println(integer); // 2 10 11 12 } 13 } 14 15 class Integer { 16 private int i; 17 18 public Integer(int i) { 19 this.i = i; 20 } 21 22 public int intValue() { 23 return i; 24 } 25 }
在上面的代碼中,如果我們想要計算出 1+1 的值,按照之前所學的我們直接利用 int 類型數據 1+1 即可獲取,但是我們在上面說了基本類型並不具備面向對象特征,那我們在某些情況下又需要怎么辦呢,這就是上面代碼中我們自己所寫的 integer 類,但是如果我們僅僅是為了計算一個 1+1 ,每次都需要實例化一些 Integer 又太小題大做了。
所以 Java 就很貼心的為八個基本類型封裝了一下,並且內置在了 lang 包內,即包裝類,所以我們的代碼如下也是可以正常運行的:
1 public class Main { 2 public static void main(String[] args) { 3 int i = 1 + 1; 4 System.out.println(i); // 2 5 6 Integer integer1 = new Integer(1); 7 Integer integer2 = new Integer(1); 8 int integer = integer1.intValue() + integer2.intValue(); 9 System.out.println(integer); // 2 10 } 11 }
包裝類是不可變類,在構造了包裝類對象后,不允許更改包裝在其中的值,包裝類是 final 的,不能定義他們的子類。
在上面的圖片中,我們可以看出,數字類型的包裝類繼承自 Number,char 和 boolean 類型的包裝類繼承自 Object,接下來我們就舉例看一下,如下代碼:
1 /** 2 * 數字類型的包裝類繼承自 Number 3 * 其提供了入:intValue,doubleValue 這樣的方法, 4 * 其作用是將當前包裝類表示的數字以其他數字類型的形式返回 5 * */ 6 public class Main { 7 public static void main(String[] args) { 8 /** 9 * 將基本類型轉換成包裝類有兩種方法: 10 * 1、調用構造方法 11 * 2、調用靜態方法 valueOf(推薦) 12 * */ 13 Integer integer1 = new Integer(1); 14 Integer integer2 = new Integer(1); 15 System.out.println(integer1 == integer2); // false 16 System.out.println(integer1.equals(integer2)); // true 17 18 Integer integer3 = Integer.valueOf(1); 19 Integer integer4 = Integer.valueOf(1); 20 System.out.println(integer3 == integer4); // true 21 System.out.println(integer3.equals(integer4)); // true 22 23 Integer integer5 = Integer.valueOf(128); 24 Integer integer6 = Integer.valueOf(128); 25 System.out.println(integer5 == integer6); // false 26 System.out.println(integer5.equals(integer6)); // true 27 } 28 }
在上面的代碼中,我們先使用實例化的方法,結果跟之前文章所講的 equals 方法時所得的結果一樣,當我們使用 valueOf() 方法時,發現 == 也變為了 true,這是因為 valueOf 會重用對象,並不會重新分配地址,但是僅限於 -128 -- 127 之間的整數。一旦超過會去 new 一個新對象。相比較而言,在 -128 -- 127 之間時,valueOf 會幫我們節省一部分內存空間,所以推薦使用 valueOf。
當然包裝類也為我們提供了轉為基本類型的方法,如下:
1 public class Main { 2 public static void main(String[] args) { 3 Integer integer = Integer.valueOf(128); 4 5 int int1 = integer.intValue(); 6 System.out.println(int1); // 128 7 8 float float1 = integer.floatValue(); 9 System.out.println(float1); // 128.0 10 11 // byte 類型為 -128 -- 127,超出會重新計算 12 byte byte1 = integer.byteValue(); 13 System.out.println(byte1); // -128 14 } 15 }
那我們怎么知道各個基本類型的最大值和最小值呢?包裝類其實已經很貼心的為我們提供了方法,如下:
1 /** 2 * 數字類型包裝類都支持兩個常量 3 * MAX_VALUE , MIN_VALUE 4 * 分別保存了對應基本類型的最大值和最小值 5 * */ 6 public class Main { 7 public static void main(String[] args) { 8 int intMax = Integer.MAX_VALUE; 9 int intMin = Integer.MIN_VALUE; 10 System.out.println(intMax); // 2147483647 11 System.out.println(intMin); // -2147483648 12 13 byte byteMax = Byte.MAX_VALUE; 14 byte byteMin = Byte.MIN_VALUE; 15 System.out.println(byteMax); // 127 16 System.out.println(byteMin); // -128 17 } 18 }
通過上面的代碼我們了解了包裝類的一些基本特征和使用方法,那我們使用包裝類的常用方法時什么呢?如下:
1 /** 2 * 包裝類提供了一個靜態方法 parseXXX(String str) 3 * 可以將給定的字符串轉換為對應的基本類型 4 * 前提是該字符串必須正確的描述基本類型可以保存的值 5 */ 6 public class Main { 7 public static void main(String[] args) { 8 String str = "123"; 9 int i = Integer.parseInt(str); 10 System.out.println(i); // 123 11 12 double d = Double.parseDouble(str); 13 System.out.println(d); // 123.0 14 15 float f = Float.parseFloat(str); 16 System.out.println(f); // 123.0 17 18 String str1 = "123.123"; 19 int i1 = Integer.parseInt(str1); 20 System.out.println(i1); // 編譯錯誤,Integer 並不能識別小數位 21 22 double d1 = Double.parseDouble(str1); 23 System.out.println(d1); // 123.123 24 } 25 }
在上面的代碼中,我們分別定義了 "123" 和 "123.123" 兩個字符串,從上面的輸出結果可以看出,只有字符串能正確額描述基本類型可以保存的值才能運行成功。
接下來我們再來看一個包裝類的自動拆裝箱
1 /** 2 * JDK1.5 以后推出的新特性 3 * 自動拆裝箱 4 */ 5 public class Main { 6 public static void main(String[] args) { 7 /** 8 * 自動拆裝箱是編譯器認可,而不是虛擬機認可 9 * 編譯器在將源程序編譯時自動補充代碼來完成基本類型與包裝類的轉換 10 * */ 11 int i = new Integer(1); // 編譯器會默認在后面加 .intValue() 12 Integer ii = 123; // 編譯器會默認變為 Integer.valueOf(123) 13 } 14 }
在上面的代碼中,我們可以看到 int 類型可以直接接受一個是實例化的包裝類,包裝類也可以直接接受一個基本類型的值,這就是自動拆裝箱,避免了我們在編寫程序時的轉換,減少了代碼量。