什么是泛型
泛型,即 “引數化型別”,一提到引數,最熟悉的就是定義方法時有形參,然后呼叫此方法時傳遞實參,那么引數化型別怎么理解呢?
顧名思義,就是通過泛型指定的不同型別來控制形參限制,在泛型使用程序中,操作的資料型別被指定為一個引數,這種引數型別可以用在類、介面和方法中,分別被稱為泛型類、泛型介面、泛型方法,
常見的泛型變數
E:元素(Element),多用于 java 集合框架
K:關鍵字(Key)
N:數字(Number)
T:型別(Type)
V:值(Value)
為什么用泛型
提高可讀性
使 ClassCastException 這種錯誤在編譯期就檢測出來
適用于多種資料型別執行相同的代碼(代碼復用)
舉個例子:
public class Add {
//普通方法實作
private static int add(int a, int b) {
System.out.println(a + "+" + b + "=" + (a + b));
return a + b;
}
private static float add(float a, float b) {
System.out.println(a + "+" + b + "=" + (a + b));
return a + b;
}
private static double add(double a, double b) {
System.out.println(a + "+" + b + "=" + (a + b));
return a + b;
}
// 泛型方法實作
private static <T extends Number> double add(T a, T b) {
System.out.println(a + "+" + b + "=" + (a.doubleValue() + b.doubleValue()));
return a.doubleValue() + b.doubleValue();
}
public static void main(String[] args) {
Add.add(1, 2);
Add.add(1f, 2f);
Add.add(1d, 2d);
System.out.println("--------------------------");
// 以下三個都是呼叫泛型方法
// 此時其實是用一個泛型方法就實作了上面三個多載方法的功能,
Add.add(Integer.valueOf(1), Integer.valueOf(2));
Add.add(Float.valueOf(1), Float.valueOf(2));
Add.add(Double.valueOf(1), Double.valueOf(2));
}
}
泛型的使用方法
泛型類
由我們指定想要傳入泛型類中的型別,把泛型定義在類上,用戶使用該類的時候,才把型別明確下來,比如:定義一個萬能的物體資料暫存工具類,
泛型類在初始化時就把型別確定了
package com.nasus.generic.how;
public class EntityTool<T> {
private T entity;
public T getEntity() {
return entity;
}
public void setEntity(T entity) {
this.entity = entity;
}
public static void main(String[] args) {
// 創建物件并指定元素型別
EntityTool<String> stringTool = new EntityTool<>();
stringTool.setEntity("一個優秀的廢人");
String s = stringTool.getEntity();
System.out.println(s);
// 創建物件并指定元素型別
EntityTool<Integer> integerTool = new EntityTool<>();
// 此時,如果這里傳入的還是 String 型別,那就會在編譯期報錯
integerTool.setEntity(10);
int i = integerTool.getEntity();
System.out.println(i);
}
}
泛型方法
泛型方法在呼叫時才確定最終型別
若有回傳值,回傳值不需要強轉
package com.nasus.generic.how;
public class Show {
public static <T> T show(T t) {
System.out.println(t);
return t;
}
public static void main(String[] args) {
// 回傳值不用強轉,傳進去是什么,回傳就是什么
String s = show("一個優秀的廢人");
int num1 = show(666);
double num2 = show(666.666);
System.out.println("------------------------");
System.out.println(s);
System.out.println(num1);
System.out.println(num2);
}
}
泛型介面
當實作類不明確泛型介面的型別引數變數時,實作類也必須定義型別引數變數
public interface Show<T> {
void show(T t);
}
public class ShowImpl<T> implements Show<T>{
@Override
public void show(T t) {
System.out.println(t);
}
public static void main(String[] args) {
ShowImpl<String> stringShow = new ShowImpl<>();
stringShow.show("一個優秀的廢人");
}
}
明確泛型介面的型別引數變數
public class ShowImpl2 implements Show<String>{
@Override
public void show(String s) {
System.out.println("一個優秀的廢人");
}
}
限定泛型型別變數
限定泛型型別上限
指定了泛型類的父類宣告類
在類中使用:
類名 <泛型標識 extends 類>{}
// 用在類上
public class Show<T extends Number> {
private T show(T t){
System.out.println(t);
return t;
}
public static void main(String[] args) {
// 初始化時指定型別
Show<Integer> show = new Show<>();
show.show(6666666);
// 報錯,該類只接受繼承于 Number 的泛型引數
// Show<String> stringShow = new Show<>();
}
}
在方法中使用
定義物件:類名 <泛型標識 extends 類> 物件名稱
public class Info<T> {
// 定義泛型變數
private T var;
public void setVar(T var) {
this.var = var;
}
public T getVar() {
return this.var;
}
public String toString() {
return this.var.toString();
}
}
public class ShowInfo {
// 用在方法上,只能接收 Number 及其子類
public static void showInfo(Info<? extends Number> t) {
System.out.print(t);
}
public static void main(String args[]) {
Info<Integer> i1 = new Info<>();
Info<Float> i2 = new Info<>();
i1.setVar(666666666);
i2.setVar(666666.66f);
showInfo(i1);
showInfo(i2);
}
}
限定泛型型別下限
定義物件:類名 <泛型標識 extends 類> 物件名稱
與指定上限相反,指定下限定很簡單,就是相當于指定了泛型類的子類,
public class ShowInfo {
// 只接受 String 的父類
public static void showInfo(Info<? super String> t) {
System.out.println(t);
}
public static void main(String args[]) {
Info<String> stringInfo = new Info<>();
Info<Object> objectInfo = new Info<>();
stringInfo.setVar("一個優秀的廢人");
objectInfo.setVar(new Object());
showInfo(stringInfo);
showInfo(objectInfo);
}
}
通配符型別
- <? extends Parent> 指定了泛型型別的上限
- <? super Child> 指定了泛型型別的下屆
- <?> 指定了沒有限制的泛型型別
泛型的使用規范
1、不能實體化泛型類
2、靜態變數或方法不能參考泛型型別變數,但是靜態泛型方法是可以的
3、基本型別無法作為泛型型別
4、無法使用 instanceof 關鍵字或 == 判斷泛型類的型別
5、泛型類的原生型別與所傳遞的泛型無關,無論傳遞什么型別,原生類是一樣的
6、泛型陣列可以宣告但無法實體化
7、泛型類不能繼承 Exception 或者 Throwable
8、不能捕獲泛型型別限定的例外但可以將泛型限定的例外拋出
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543164.html
標籤:Java
