Java中的泛型詳解
所謂泛型:就是允許在定義類別、介面指定類型形參,這個類型形參在將在宣告變數、建立物件時決定(即傳入實際的型別參數,也可稱為型別實參)
泛型類別或介面
「菱形」語法
//定义 public interface List<E> extends Collection<E> public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable //使用 List<String> list = new ArrayList(); //Java7以后可以省略后面尖括号的类型参数 List<String> list = new ArrayList<>();
從泛型類派生子類
//方式1 public class App extends GenericType<String> //方式2 public class App<T> extends GenericType<T> //方式3 public class App extends GenericType
偽泛型
不存在真正的泛型類,泛型類對Java虛擬機來說是透明的. JVM並不知道泛型類別的存在,換句話說,JVM處理泛型類別和普通類別沒什麼區別的.因此在靜態方法、靜態初始化區塊、靜態變數裡面不允許使用類型形參。
- 以下方式都是錯誤的
private static T data; static{ T f; } public static void func(){ T name = 1; }
下面的例子可以從側面驗證不存在泛型類
public static void main(String[] args){ List<String> a1 = new ArrayList<>(); List<Integer> a2 = new ArrayList<>(); System.out.println(a1.getClass() == a2.getClass()); System.out.println(a1.getClass()); System.out.println(a2.getClass()); }
輸出
true class java.util.ArrayList class java.util.ArrayList
類型通配符
首先必須明確,假如FooListBar是一點的父類,但< Foo>並不是List
以下方法會編譯出錯:
List<?> list = new ArrayList<>(); list.add(new Object());
主意幾點:
1.List
2.陣列和泛型有所不同:假設Foo是Bar的一個子型別(子類別或子介面),那麼Foo[]依然是Bar[]的子型別;但G
3.為了表示各種泛型List的父類,我們需要使用類型通配符,類型通配符是一個問號(?),將一個問號作為類型實參傳給List集合,寫作:List>(意思是未知類型元素的List)。這個問號(?)被稱為通配符,它的元素類型可以匹配任何類型。
通配符的上限
List extends SuperType>表示所有SuperType泛型List的父類或本身。有通配符上限的泛型不能有set方法,只能有get方法。
設定通配符上限能解決如下問題:Dog是Animal子類,有個getSize方法要獲取傳入List的個數,代碼如下
abstract class Animal { public abstract void run(); } class Dog extends Animal { public void run() { System.out.println("Dog run"); } } public class App { public static void getSize(List<Animal> list) { System.out.println(list.size()); } public static void main(String[] args) { List<Dog> list = new ArrayList<>(); getSize(list); // 这里编译报错 } }
這裡編程出錯的原因是List
通配符的下限
List super SubType>表示SubType泛型List的下限。有通配符上限的泛型不能有get方法,只能有set方法。
泛型方法
如果定義類別、介面是沒有使用型別形參,但定義方法時想自己定義型別形參,這也是可以的,JDK1.5也提供了泛型方法的支援。泛型方法的方法簽名比普通方法的方法簽名多了類型形參聲明,類型形參聲明以尖括號括起來,多個類型形參之間以逗號(,)隔開,所有類型形參聲明放在方法修飾符與方法傳回值型別之間.語法格式如下:
修饰符 返回值类型 方法名(类形列表){ //方法体 }
泛型方法允許型別形參被用來表示方法的一個或多個參數之間的型別依賴關係,或是方法傳回值與參數之間的類型依賴關係。如果沒有這樣的類型依賴關係,就不應該使用泛型方法。 Collections的copy方法就使用泛型方法:
public static <T> void copy(List<? super T> dest, List<? extends T> src){ ...}
這個方法要求src型別必須是dest型別的子類別或本身。
擦除和轉換
在嚴格的泛型程式碼裡,帶有泛型聲明的類別總是應該帶著型別參數。但為了與舊的Java程式碼保持一致,也允許在使用帶有泛型聲明的類別時不指定類型參數。如果沒有為這個泛型類別指定型別參數,則該型別參數被稱為一個raw type(原始型別),預設是該宣告該參數時指定的第一個上限型別。
當把一個具有泛型資訊的物件賦給另一個沒有泛型資訊的變數時,則所有在尖括號之間的類型資訊都被丟掉了。比如說一個List
範例
class Apple<T extends Number> { T size; public Apple() { } public Apple(T size) { this.size = size; } public void setSize(T size) { this.size = size; } public T getSize() { return this.size; } } public class ErasureTest { public static void main(String[] args) { Apple<Integer> a = new Apple<>(6); // ① // a的getSize方法返回Integer对象 Integer as = a.getSize(); // 把a对象赋给Apple变量,丢失尖括号里的类型信息 Apple b = a; // ② // b只知道size的类型是Number Number size1 = b.getSize(); // 下面代码引起编译错误 Integer size2 = b.getSize(); // ③ } }
更多Java中的泛型詳解相關文章請關注PHP中文網!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

在使用IntelliJIDEAUltimate版本啟動Spring...

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

在使用TKMyBatis進行數據庫查詢時,如何優雅地獲取實體類變量名以構建查詢條件,是一個常見的難題。本文將針...
