Java泛型
- 2021 年 1 月 30 日
- 筆記
你要做一個不動聲色的大人了。不準情緒化,不準偷偷想念,不準回頭看。去過自己另外的生活。你要聽話,不是所有的魚都會生活在同一片海里。 ——村上春樹 《舞!舞!舞!》
Q:什麼是泛型?

-
Java泛型本質:參數化類型
從字面意思就可以看出,就是把「類型變成了參數」,如String類型、Integer類型等都作為參數。
==============================================================================
-
泛型-承擔「保安」的角色

-
Q:泛型如何使用?
1.List mylist1=new ArrayList();//未使用泛型;
2.List<String> mylist2=new ArrayList<String>();//參數化類型;
- 集合類容納的對象都是Object類的實例。也就是說字元串或整型數據等都能存入List列表中,因為Object類是所有類的父類。
=============================================================================
下面看看未使用泛型和使用了泛型的區別:
- 未使用泛型:

-
字元串數據、整型數據等都能存入List列表中,List列表把這些數據都看作時Object類型,當我們只想取出某種類型
數據時,需要進行強制轉換。如上圖,字元串強轉字元串這個沒啥問題,但是整型強轉字元串類型就會運行報錯,出現
ClassCastException錯誤(類型不匹配)。
=============================================================================
- 使用泛型:

如上述程式碼,
如果不是就會被攔截(報錯)。把String作為參數,類型參數化,這就是泛型。當然你可以把其他類型作為參數。
=============================================================================
Q:泛型有什麼作用?

類型參數——類型實參與類型形參
-
類型參數可以類比Java方法中的形參和實參,類型實參就如我前面舉的例子,那類型形參長什麼樣呢?
-
看下圖:API文檔中List介面的定義

-
這很顯然使用了泛型,但它不是確定的數據類型,這就是類型形參。泛型中使用大寫的英文字母來作為類型形參。
-
這裡的E是一個類型形參,實際中你可以寫成String、Integer等等。
=============================================================================
菱形運算符
List<String> mylist2=new ArrayList<String>();
-
上述程式碼中,mylist2是List
類型的,顯然創建的對象也必須是List 類型的,任何其他類型的參數都會產生編譯錯誤。 Java7增加了一種新的語言特性,稱為菱形運算符,上面程式碼可改寫為:
List<String> mylist2=new ArrayList<>();
泛型通配符
- 無界通配符
- 上界通配符
- 下界通配符
1.程式碼示例:PrintList方法列印任何類型的列表
public static void PrintList(List<Object> list) {
for (Object o: list)//增強型for循環列印列表
System.out.println(o + " ");
}
//The method PrintList(List<Object>) in the type PrintList is not applicable for the arguments (List<Integer>)
//不能列印List<Integer>, List<String>等等,因為它們不是List<Object>的子類型(只存儲整型的列表不是可存儲任何類型的列表的子類)。
//使用通配符(?):表示未知類型,即可以是String類型,也可以是Integer類型等等。
public static void PrintList(List<?> list){}
2/3.程式碼示例:
class Food {}//食物類
class Fruit extends Food {}//水果類
class Apple extends Fruit {}//蘋果類
public class Plate<T> {//盤子類(泛型類)
public Plate(T t){item=t;}
public void set(T t){item=t;}//放和取操作
public T get(){return item;}
private T item;
public static void main(String[] args) {
//定義水果盤子
Plate<Fruit> p1=new Plate<Apple>(new Apple());//Error 🍎與水果有繼承關係,但🍎盤子與水果盤子之間沒繼承關係
//<? extends T>上界通配符,中間表示T及任何T的派生類的類型數據,這個例子中理解為『這個盤子能裝任何水果』,蘋果當然沒問題
//能裝任何水果的盤子與蘋果盤子之間就有了繼承關係(Plate<? extends Fruit> 是Plate<Apple>的基類)
Plate<? extends Fruit> p1=new Plate<Apple>(new Apple());
//<? extends T>不能往裡存,只能往外取。是水果就能放進來,但編譯器並不知道是什麼水果,當要對蘋果賦值時,編譯器找不到。
p1.set(new Fruit()); //Error
//讀取出來的東西只能存放在Fruit或它的基類里。從水果盤子里來的肯定是水果,或者是食物(基類)
Fruit newFruit1=p1.get();
Object newFruit2=p1.get();
Apple newFruit3=p1.get(); //Error
//<? super Fruit>下界通配符,表示T及任何T的基類的類型數據,這個例子中理解為『這個盤子能裝任何食物(水果基類)』。
Plate<? super Fruit> p2=new Plate<Fruit>(new Fruit());
//<? super T>不影響往裡存,但往外取只能放在Object對象里
p2.set(new Fruit());
p2.set(new Apple());
Apple newFruit4=p2.get(); //Error
Fruit newFruit5=p2.get(); //Error
Object newFruit6=p2.get();
}
}
上界下界參考> //blog.csdn.net/hello_worldee/article/details/77934244
簡單泛型類和介面
public class GenericMemoryCell <E> {//泛型類
public E read()
{return Value;}
public void write(E x)
{Value=x;}
private E Value;
}
package java.lang
//泛型介面,Comparable介面;
public interface Comparable<E>
{
public int compareTo(E other)
}
註:參考百度百科及《數據結構與演算法分析》


