包裝類+泛型
- 一、包裝類
- (1)基本數據類型和對應的包裝類
- (2)裝箱和拆箱
- 二、泛型
- (1)什么是泛型
- (2)引出泛型
- (3)語法
- (4)泛型類的使用
- 1.語法
- 2.示例
- 3.類型推導
- (5)裸類型
- (6)泛型是如何編譯的
- 1.擦除機制
- 2.為什么不能實例化泛型類數組?
- (7)泛型的上界
- 1.語法
- 2.示例
- 3.復雜示例
- (8)泛型方法
- 1.語法
- 2.示例
一、包裝類
在Java中,由于基本類型不是繼承自Object
,為了在泛型代碼中可以支持基本類型,Java給每個基本類型都對應了一個包裝類型
(1)基本數據類型和對應的包裝類
基本數據類型 | 包裝類 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
- 除了
Integer
和character
,其余基本類型的包裝類都是首字母大寫
(2)裝箱和拆箱
- 裝箱:把一個基本數據類型轉化為包裝類型的過程
- 拆箱:將一個包裝類中的值取出,放到一個基本類型中
自動裝箱與自動拆箱
public class demo {public static void main(String[] args) {//自動裝箱int i = 10;Integer a = i;//自動拆箱int b = a;}
}
顯示裝箱和顯示拆箱
//顯示裝箱int c = 20;Integer d = Integer.valueOf(c);//顯示拆箱:拆箱為自己指定的元素int e = d.intValue();double e1 = d.doubleValue();
二、泛型
(1)什么是泛型
一般的類和方法,只能使用具體的類型,要么是基本類型,要么是自定義的類,如果要編寫可以應用于多種類型的代碼,這種刻板的限制對代碼的束縛就會很大。—— 《Java編程思想》
泛型是在jdk1.5引入的新語法,通俗講,泛型:就是適用于許多許多類型,從代碼上將,就是對類型實現了參數化
(2)引出泛型
實現一個類,類中包含一個數組成員,使得數組中可以存放任何類型的數據,也可以根據成員方法返回數組中某個下標的值?
思路:
- 我們以前學過的數組,只能存放指定類型的數據,例如
String[]
、int[]
- 所有類的父類,默認為
Object
類,數組是否可以創建為Object
?
class MyArray{Object[] array = new Object[10];public void set(int pos,Object val){this.array[pos] = val;}public Object get(int pos){return this.array[pos];}
}
public class demo1 {public static void main(String[] args) {MyArray myArray = new MyArray();myArray.set(0,10000);myArray.set(1,"hello");String ret = myArray.get(1);//編譯報錯String ret = (String) myArray.get(1);}
}
以上代碼實現后發現
- 任何類型數據都可以存放
- 1號下標本身就是字符串,但是卻編譯報錯,必須進行強制類型轉換才可以
雖然在這種情況下,當前數組任何數據都可以存放,但是,更多情況下,我們還是希望他只能夠持有一種數據類型,而不是同時持有這么多類型,所以,泛型的主要目的:指定當前的容器,要持有什么類型的對象,讓編譯器去做檢查,此時,就需要把類型作為參數傳遞,需要什么類型,就傳入什么類型
(3)語法
class 泛型類名稱<類型形參列表>{//這里可以使用類型參數
}
class ClassName<T1,T2……Tn>{}
class 泛型類名稱<類型形參列表> extends 繼承類{//這里可以使用類型參數
}
class ClassName<T1,T2……Tn> extends ParentClass<T1>{//可以只使用部分類型參數
}
上述代碼進行改寫如下
class Myarray<T>{Object[] array = new Object[10];public void set(int pos,T val){this.array[pos] = val;}public T get(int pos) {return (T)this.array[pos];}
}
public class demo2 {public static void main(String[] args) {Myarray<String> myArray = new Myarray<>();myArray.set(0,"sadfklsajdfs");myArray.set(1,"qwe");String ret = myArray.get(0);String ret1 = myArray.get(1);System.out.println(ret);System.out.println(ret1);Myarray<Integer> myarray = new Myarray<>();myarray.set(0,3);Integer ret2 = myarray.get(0);System.out.println(ret2);}
}
//輸出結果
sadfklsajdfs
qwe
3Process finished with exit code 0
代碼解釋:
- 類名后的代表占位符,表示當前類是一個泛型類
類型形參一般使用一個大寫字母來表示,常用的名稱有
- E表示
Element
- K表示
Key
- V表示
Value
- N表示
Number
- T表示
Type
- 不能new泛型類型的數組
T[] ts = new T[5];//是不對的
- 類型后需要加入包裝類指定當前類型
Myarray<String> myArray = new Myarray<>();
- 存放元素的時候會幫我們檢查,如果和包裝類不同,會報錯提示
(4)泛型類的使用
1.語法
泛型類<類型實參> 變量名 = new 泛型類<類型實參>(構造方法實參);
2.示例
尖括號中只能是引用類型,不能是基本類型
Myarray<String> myArray = new Myarray<String>();
注意:泛型只能接受類,所有的基本數據類型必須使用包裝類
3.類型推導
當編譯器可以根據上下文推導出類型實參時,可以省略類型實參的填寫,但是尖括號不能省略
Myarray<String> myArray = new Myarray<>();
(5)裸類型
裸類型是一個泛型類但是沒有帶著類型實參
Myarray list = new Myarray();
注意:我們不要自己去使用裸類型,裸類型是為了兼容老版本的API保留的機制
(6)泛型是如何編譯的
1.擦除機制
那么,泛型到底是怎么編譯的呢?這個問題也是曾經的一個面試問題,泛型本質是一個非常難的語法,要理解好它還是需要一定的時間打磨
我們先察看字節碼文件,發現所有的T
都是Object
- 在編譯的過程中,將所有的
T
替換為Object
這種機制,我們稱為擦除機制 - 運行的時候沒有泛型這樣的概念,泛型的擦除機制,只存在于編譯期間
2.為什么不能實例化泛型類數組?
原因:替換后的方法為:將Object[]
分給Integer[]
引用,程序報錯
不能證明所有類型都是Integer
類型
通俗講就是:返回的Object
數組里面,可能存放的是任何的數據類型,可能是String
,可能是Integer
,運行的時候,直接傳給Integer
類型的數組,編譯器認為是不安全的
(7)泛型的上界
在定義泛型類時,有時需要對傳入的類型變量做一定的約束,可以通過類型邊界來約束
1.語法
class 泛型類名稱<類型實參 extends 類型邊界>{}
2.示例
class test<E extends Number>{}
extends
表示拓展,只接受Number
的子類型作為E的類型實參
class test<E extends Number>{}
public class demo4 {public static void main(String[] args) {test<Integer> a1;//正常,因為Integer是Number的子類型test<String> a2;//編譯錯誤,因為String不是Number的子類型}
}
沒有指定類型邊界E
,可以視為E extends Object
3.復雜示例
寫一個泛型類,實現一個方法,這個方法是就指定類型泛型的最大值
class Alg<T extends Comparable<T>>{public T findMax(T[] array){T max = array[0];for (int i = 1; i < array.length; i++) {if(array[i].compareTo(max) > 0){max = array[i];}}return max;}
}
public class demo5 {public static void main(String[] args) {Alg<Integer> alg1 = new Alg<>();Integer[] array = {1,2,3,4,5};Integer ret = alg1.findMax(array);System.out.println(ret);}
}
//輸出結果
5Process finished with exit code 0
(8)泛型方法
1.語法
方法限定符<類型形參列表> 返回值類型 方法名稱(形參列表){}
2.示例
class Util{public <T extends Comparable<T>> T findMax(T[] array){T max = array[0];for (int i = 1; i < array.length; i++) {if(array[i].compareTo(max) > 0){max = array[i];}}return max;}
}
public class demo6 {public static void main(String[] args) {Util util = new Util();Integer[] array = {1,2,3,4,5};Integer ret = util.findMax(array);System.out.println(ret);}
}
//輸出結果
5Process finished with exit code 0
靜態方法可以直接通過類名調用
class Util{public static <T extends Comparable<T>> T findMax(T[] array){T max = array[0];for (int i = 1; i < array.length; i++) {if(array[i].compareTo(max) > 0){max = array[i];}}return max;}
}
public class demo6 {public static void main(String[] args) {Integer[] array = {1,2,3,4,5};Integer ret = Util.findMax(array);System.out.println(ret);}
}
//輸出結果
5Process finished with exit code 0