java泛型中,上下界通配符(跟)

背景介紹:java中的泛型,是在java5.0後才引用的,泛型,可讓咱們更安全的操做容器,而不用擔憂出現讓人很是不快的ClassCastException異常,可是泛型沒有多態的概念,Sun的那羣大腦殼,就想到了一個解決辦法,就是上界通配符<? extends T>,跟下界通配符(<? super T>),下面就介紹一下我的對它的理解吧,

 

首先,咱們先定義幾個類:java

Leve2

class Food{}

Leve2

class Fruit{}
class Meat{}

Leve3

class Apple{}
class WaterMelon{}

 

繼承關係圖以下:安全

 

而後咱們定義2個不使用通配符的方法:app

/**
	 * 不使用上界通配符
	 */
	public static void isUpMethod(List<Fruit> list){

	}


	/**
	 * 不使用下界通配符
	 */
	public static void isDownMethod(List<Fruit> list){

	}

 

接着,咱們使用2個List,放函數裏面存參數:函數

List<Apple> apples = new ArrayList<>();

		apples.add(new Apple());
		apples.add(new Apple());
		apples.add(new Apple());

		//兩個方法編譯會報錯
		//isUpMethod(apples);
		//isDownMethod(apples);

		List<Fruit> fruits = new ArrayList<>();

		fruits.add(new Fruit());
		fruits.add(new Fruit());
		fruits.add(new Fruit());

		//編譯經過
		isUpMethod(fruits);
		isDownMethod(fruits);

有同窗就會問了,List的泛型指定了Fruit類型,另一個List泛型指定了Apple確定編譯不過去啊,可是,別忘了,Apple是Fruit的子類,咱們理解中 Fruit fruit = new Apple();是可行的,由於java的多態;

可是,泛型是沒有多態的,它可不認爲Apple是Fruit的子類,若是這樣的話,爲代碼重用代碼很大的麻煩,由於泛型只是編譯級別,在運行期間,泛型是會擦除的;

PS:指定泛型集合後,往內添加的元素能夠是Fruit的子類,由於會自動向上轉型,觸發多態

若是想isUpdownMethod或者isDownMethod函數,接收其泛型類的子類或者父類,這時候,咱們就可使用上界通配符了<? extends Fruit>跟下界通配符<? super Fruit>

 

咱們定義一個以下函數:ui

/**
	 * 上界通配符
	 */
	public static void upMethod(List<? extends Fruit> list){
		//編譯報錯
		//使用通配符後,不能在往集合類中添加元素
		//list.add();


		//使用通配符後,是能夠取出元素的
		//全部取出的元素,都是上界父類元素
		Fruit fruit = list.get(0);
	}


	/**
	 * 下界通配符
	 */
	public static void downMethod(List<? super Fruit> list){
		//下界通配符能夠往容器內添加元素
		//可是有限制,必須是Fruit的子類或者自己,父類是添加不進去的
		list.add(new Apple());

		//取出元素的類型都爲Object
		Object object = list.get(0);
	}

而後,咱們試試使用往函數類傳輸LIST集合泛型指定是子類的集合:spa

List<Apple> apples = new ArrayList<>();

		apples.add(new Apple());
		apples.add(new Apple());
		apples.add(new Apple());


		List<Fruit> fruits = new ArrayList<>();

		fruits.add(new Fruit());
		fruits.add(new Fruit());
		fruits.add(new Fruit());

		List<Food> foods = new ArrayList<>();

		foods.add(new Food());
		foods.add(new Food());
		foods.add(new Food());
		
		//編譯經過
		upMethod(apples);
		upMethod(fruits);
		
		//編譯經過
		downMethod(fruits);
		downMethod(foods);

 

 

上界通配符<? extends Fruit>

簡介:code

  •     上界通配符中的上界,指的是泛型內的類型,最高是Fruit類,最低不限,只要是繼承了Fruit類,均可以經過編譯,這也就是爲何叫 "上界",最高類型就是Fruit類          

描述:

  • 在upMethod函數中,使用上界通配符後,限定了條件,傳參對象的泛型,必須是Fruit類或者其子類,才能經過編譯,不然,編譯就會失敗,

  • 特性:
    • 在使用上界通配符後,咱們不能在往集合內添加元素,那是由於,雖然指定了泛型的類型是Fruit類或者其子類,可是Fruit類可能並不止一個子類,可能除了Apple外還有Banana或者Watermelon類,若是你傳遞進來的是Apple集合,可是往裏面添加Banana,這種狀況下,往外取元素的時候很大的可能性會出現異常,由於取出的元素不是Apple而是Banana.因此,避免出現這種狀況,使用上界通配符後,是不能再往集合內添加元素,
    • 能夠往外取元素,全部取出的元素都是Fruit類,由於,編譯器只知道是Fruit的子類,可是殊不知道是具體哪一個子類,因此取出的元素是最高層的類,也就是Fruit類

 

 

---------------------------------分割線----------------------------------------對象

 

 

下界通配符<? super Fruit>描述:

簡介:繼承

  •     下界通配符中的下界,指的是泛型內的類型,最低是Fruit類,最高到超類Object,只要是Fruit的父類,均可以經過編譯,這也就是爲何叫 "下界",由於最低是Fruit類       

描述:

  • 在downMethod函數中,使用下界通配符後,限定了條件,傳參對象的泛型,必須是Fruit類或者其父類,才能經過編譯,不然,編譯就會失敗,

  • 特性:
    • 能夠往集合內添加元素,可是限制條件是往內添加的元素,必須是Fruit的子類,由於雖然知道是Fruit的基類 但也不知道是往上數多少級的基類 只有Fruit以及它的子類 編譯器才能判定能觸發多態,
    • 能夠往外取元素,可是取出來的元素都是Object,由於取出來的有多是Food,比Fruit範圍大,不能賦值給Fruit對象。只有Object能夠,由於沒有類比Object大。

 

 

---------------------------------分割線----------------------------------------內存

有人可能會問,爲何使用上界通配符後,不能往裏存元素了,可是使用下界通配符能往裏面存元素,緣由以下:

  1. 上界通配符指定了上限,最高就是Fruit類,往裏存元素,不是Fruit就是其子類啊,理論上是能夠往內存的,那是由於使用上界通配符後,雖然有上限,可是沒有下限啊,編譯器,只知道是Fruit類或者是Fruit的子類,可是具體是哪一個類型的子類,編譯器也不知道,爲了防止出現類型轉換錯誤,因此,就禁止再往內添加元素(若是是我,我也會這麼作,避免出現這樣的狀況)

  2. 下界通配符能往內存元素是由於下界通配符,規定了最小粒度的下限,是Fruit類.其實是放鬆了對元素的類型控制,既然元素是Fruit類的父類,那往裏存Fruit子類確定能夠的,由於Fruit的子類,也是其Fruit父類的子類,

  3. 上界通配符<? extends Fruit> 能夠當作<?> 類型都不知道,確定不讓往裏面添加元素,由於沒有下限;也能夠當作是一個能夠放某種Fruit的集合,不是一個能夠聽任何Fruit的大雜燴集合
  4. 下界通配符<? super Fruit> 能夠當作<Fruit>,肯定了類型最低是Fruit,因此能夠往內添加元素,可是必須是Fruit或者其子類​​​​​​​;也能夠當作是一個能夠聽任何Fruit的集合

 

---------------------------------分割線----------------------------------------

 

總結:

  •         上界通配符<? extends T> 指的是,引用內的泛型範圍,最高是T類,最低不限
    • 能夠取元素
    • 不能添加元素
  •         下界通配符<? super T> 指的是,引用內的泛型範圍,最低是T類,最高是超類Object
    • 能夠取元素,可是取出的元素是Object
    • 能夠添加元素,添加的元素,必須是T類或者其子類

 

到這,文章就結束了!

以上,均爲本人理解,若是理解錯誤,歡迎指正

歡迎轉載,請註明出處跟做者,謝謝!

相關文章
相關標籤/搜索