Java泛型之上、下界萬用字元的理解(適合初學)
泛型的由來
為什麼需要泛型
Java的資料型別一般都是在定義時就需要確定,這種強制的好處就是型別安全,不會出現像弄一個ClassCastException的資料給jvm,資料安全那麼執行的class就會很穩定。但是假如說我不知道這個引數要傳什麼型別的,因為公司需求在變,如果寫死的那就只能便以此需求就改一次,很麻煩。sun公司也注意到這個問題,這樣會讓程式碼的靈活性降低,他們就研究出了泛型。
泛型初識
什麼是泛型,可以字面理解就是一個泛泛的型別,他是不確定的,在Java程式碼編譯的時候用泛型是不會出錯的,而在執行期時就會報錯,說你這種第一是不合理的。這是為什麼呢。因為為了提高靈活性,就在編譯時期將條件放寬,但是泛型一定要在執行的時候告訴jvm你給我的資料到底是什麼型別的,否則jvm會是懵逼的。所以泛型的好處就是將型別的靈活性提高,也只是在Java語法的基礎上提高,不過泛型還是比較實用的。
何時使用泛型
泛型的應用場景就是應用在模型(可以理解為儲存資料的盒子),我為了這個盒子適用更多的地方我就用將需要存入的資料用一個泛型表示,當然可以傳入多值。如果是相同型別的物件就用一個泛型的陣列比較好,學過集合的小夥伴應該都知道,沒學過的那你應該補補課了。
泛型的語法
public class A<T extends B>{
T t;
}
泛型的缺點或者為什麼需要上、下邊界
泛型的雖然強大,但是世界上任何東西東部是完美的。它也有缺陷。比如說我有一個盒子我想裝蘋果,但是我還可能想裝香蕉那怎麼辦。那還不好說,在給一個引數不就行了,那十個呢,二十個呢。em....的確是。如果說我們想裝的東西都屬於一個類並且只要是這個類的子類就可以裝。這個想法sun為我們想好了。那就是用上邊界萬用字元。語法是
上邊界Java程式碼
public class Dish<T extends Fruit>{ private T fruitChild; public Dish(T fruitChild){ this.fruitChild = fruitChild; } public T getFruitChild(){ return fruitChild; } public void setFruitChild(T f){ this.fruitChild = f; } public static void main(String[] args){ Dish dish = new Dish<apple>(); Apple apple = new apple(); //apple must be Fruit child; dish.setFruitChild(apple); system.out.printf(dish.getFruitChild); } }
下邊界Java程式碼
public class Dish<T super Apple>{
private T appleFather;
public Dish(T appleFather){
this.appleFather = appleFather;
}
public T getAppleFather(){
return appleFather;
}
public void setAppleFather(T f){
this.appleFather = f;
}
public static void main(String[] args){
Dish dish = new Dish<Fruit>();
Fruit fruit = new Fruit(); //fruit must be apple son;
dish.setAppleFather(fruit);
system.out.printf(dish.getAppleFather);
}
}
什麼是上邊界萬用字元
當泛型T給定形如
上邊界萬用字元理解
什麼是下邊界萬用字元
當泛型T給定形如
下邊界萬用字元理解
上下邊界萬用字元的缺點
上界<? extends T>不能往裡存,只能往外取。
解釋
因為編譯器只知道傳入的是T的子類,但具體是哪一個編譯器不知道,他只標註了一個佔位符,當?傳過來時,他不知道這能不能和佔位符匹配,所以set不了。
下界<? super T>不影響往裡存,但往外取只能放在Object物件裡。
解釋
因為下邊界已經限制了?的粒度,他只可能是T本身或者是T的父類。我們想想,我想要一個T,你卻返回給我一個比T小的Object,這樣我們就因為精度損失而拿不到想要的資料了。
感謝各位童鞋的閱讀,希望大家動一動發財的小手點一下推薦QAQ。