包裝類
什么是包裝類
在講基本數據類型的時候,有提到過包裝類。
基本數據類型 | 包裝類 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
我們知道:基本數據類型并不是對象,沒有對象所具有的方法和屬性。為了讓基本數據類型能像對象一樣使用,Java提供了包裝類。
用途:
1、作為對象使用:提供了一些對基本類型的數據進行操作的方法。將字符串轉整數、求數據類型的范圍等等。
2、在泛型中的應用:對于什么泛型等下再講。泛型只能使用對象類型,不能使用基本數據類型,這是需要包裝類。
3、集合框架:集合(用于存儲和操作一組對象的框架,如:ArrayList等)只能存儲對象,不能存儲基本數據類型,這是需要包裝類。
裝箱和拆箱
代碼案例:
1、
public static void main(String[] args) {int a = 200;Integer integer = Integer.valueOf(a);//手動裝箱System.out.println(integer);Integer integer1 = new Integer(a);//手動裝箱System.out.println(integer1);Integer integer2 = a;//自動裝箱System.out.println(integer1);System.out.println("=============");int j = integer.intValue();//手動拆箱System.out.println(j);int jj = integer;//自動拆箱System.out.println(jj);
}
2、
public static void test() {Integer a = 100;Integer b = 100;System.out.println(a == b);//輸出:trueInteger c = 200;Integer d = 200;System.out.println(c == d);//輸出:false
}
代碼解釋:
1、
裝箱操作:就是將基本數據類型轉換為對應的包裝類對象的過程。
拆箱操作:就是把包裝類對象轉換為對應的基本數據類型的過程。
手動裝箱:調用包裝類的構造方法或者valueOf()
方法。
手動拆箱:調用包裝類的xxxValue()方法,其中xxx代表的是基本數據類型,如intValue()
、doubleValue()
等。
對于編譯器來說,會自動的裝箱和拆箱。但要注意的是:在自動拆箱時,如果包裝類對象為null,會拋出NullPointerException異常。
2、
為啥第二個輸出false?
我們知道這是完成了自定裝箱,調用了valueOf()
方法。我們來看一下valueOf()
方法。
這時候我們發現當i在一個范圍時,會指向同一個Integer對象(來自緩存)。此時使用==比較時,比較的是對象的引用,他們引用的是同一個對象,輸出true。
當不再范圍時,會各自創建一個新的Integer對象。此時使用==比較時,比較的是對象的引用,他們引用的不是同一個對象,輸出false。
通過這個緩存,找到了其范圍。-128 ~ 127
泛型
什么是泛型
泛型:就是適用于許多許多類型。從代碼上來說,就是實現了對類型的參數化。
種類
1、泛型類
代碼案例:
public class Box<T> {private T content;public T getContent() {return content;}public void setContent(T content) {this.content = content;}public Box(T content) {this.content = content;}
}
public static void test1() {Box<Integer> box1 = new Box<>();//Box<Integer> box1 = new Box<Integer>();box1.setContent(10);System.out.println(box1.getContent());System.out.println("============");Box<String> box2 = new Box<>();box2.setContent("World");box2.setContent(10);//報錯System.out.println(box2.getContent());
}
public static void test2() {Box box = new Box(10);//不會報錯,但有警告Box box2 = new Box("Hello");//不會報錯,但有警告
}
代碼解釋:
1、對于test1()中的new Box<>()
的<>中類型可寫可不寫
2、當你指定了類型時(也就是<>中的類型),存放類型不匹配時,編譯器會報錯。
3、對于test2()中,直接沒有<>明確指出類型,此時編譯器會自動判斷。但最好不要這樣寫代碼。
泛型的上界
當我們相對傳入的類型進行約束,可以規定泛型的邊界。
語法:
class 泛型類名稱<T extends 類型邊界> {
}
代碼案例:
1、
public class MyArray<T extends Number> {private final Object[] array = new Object[10];public T getPos(int pos) {return (T)this.array[pos];}public void setVal(int pos,T val) {this.array[pos] =val;}
}
public class Test {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>();myArray.setVal(0,10);System.out.println(myArray.getPos(0));MyArray<Number> myArray1 = new MyArray<>();MyArray<String> myArray2 = new MyArray<>();//報錯}
}
2、
class Max<T extends Comparable<T>> {public T findMax(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if(max.compareTo(array[i]) < 0) {max = array[i];}}return max;}
}public class Test {public static void main(String[] args) {Max<Integer> maxInteger = new Max<>();Integer[] integers = {1,2,33,65,7};Integer max = maxInteger.findMax(integers);System.out.println(max);}
}
代碼解釋:
1、class MyArray<T extends Number>
就規定了T的上界是Number類,此時T的類型只能是Number的子類或這本身。
2、泛型沒有下界
3、沒有指定類型邊界T,可以視為T extends Object
4、代碼案例二,實現了比較T類型數組中的最大值。在if語句中我們使用了Comparable接口的compareTo方法。(由于傳入的T類型不都能用 < 或 > 簡單的進行比較,會像下圖一樣報錯)
2、泛型方法
代碼案例:
1、
class Swap {public static <T> void swap(T[] array, int i,int j) {T temp = array[i];array[i] = array[j];array[j] = temp;}
}
public class Test<T> {private static<T> void printArray(T[] array) {for (int i = 0; i < array.length; i++) {System.out.print(array[i]+" ");}System.out.println();}public T find(T[] array,int pos) {return array[pos];}public static void main(String[] args) {Integer[] intArray = {1,2,3,4,5};Swap.swap(intArray,2,3);printArray(intArray);System.out.println("=====");String[] stringArray = {"Hello","World"};Swap.swap(stringArray,0,1);printArray(stringArray);System.out.println("=====");Test<Integer> integerTest = new Test<>();System.out.println(integerTest.find(intArray, 4));}
}
2、
public class Test {public static <T extends Comparable<T>> T findMax(T[] array) {T max = array[0];for (int i = 1; i < array.length; i++) {if(max.compareTo(array[i]) < 0) {max = array[i];}}return max;}public static void main(String[] args) {Integer[] integers = {1,2,33,65,7};Integer max = findMax(integers);System.out.println(max);}
}
代碼解釋:
1、對于普通方法,new對象的時候,根據<>中的類型知道T的類型(例如:find()
)。而對于靜態方法,由于是通過類名調用方法,此時編譯器就不知道 T 到底是什么類型,這時候需要在static后面加上<T>
,編譯器就會根據傳入的參數來判斷 T 是什么類型。(例如:swap()
和 printArray()
)
2、對于Swap類后面可加<T>可不加<T>
3、對剛才實現的找最大值方法改成靜態方法并加入邊界。
3、泛型接口
在學習接口的時候就有涉及到。Comparable接口就是一個泛型接口。
public interface Comparable<T> {public int compareTo(T o);
}