Java泛型中 extends和super
Java泛型中的extends和super理解
在平時看原始碼的時候我們經常看到泛型,且經常會看到extends和super的使用,看過其他的文章裡也有講到上界萬用字元和下屆萬用字元,總感覺講的不夠明白。這裡備註一下,以免忘記。
extends也稱為上界萬用字元,就是指定上邊界。即泛型中的類必須為當前類的子類或當前類。
super也稱為下屆萬用字元,就是指定下邊界。即泛型中的類必須為當前類或者其父類。
這兩點不難理解,extends修飾的只能取,不能放,這是為什麼呢?
先看一個列子:
public class Food {}
public class Fruit extends Food {}
public class Apple extends Fruit {}
public class Banana extends Fruit{}
public class GenericTest {
public void testExtends(List<? extends Fruit> list){
//報錯,extends為上界萬用字元,只能取值,不能放.
//因為Fruit的子類不只有Apple還有Banana,這裡不能確定具體的泛型到底是Apple還是Banana,所以放入任何一種型別都會報錯
//list.add(new Apple());
//可以正常獲取
Fruit fruit = list.get(1);
}
public void testSuper(List<? super Fruit> list){
//super為下界萬用字元,可以存放元素,但是也只能存放當前類或者子類的例項,以當前的例子來講,
//無法確定Fruit的父類是否只有Food一個(Object是超級父類)
//因此放入Food的例項編譯不通過
list.add(new Apple());
// list.add(new Food());
Object object = list.get(1);
}
在testExtends方法中,因為泛型中用的是extends,在向list中存放元素的時候,我們並不能確定List中的元素的具體型別,即可能是Apple也可能是Banana。因此呼叫add方法時,不論傳入new Apple()還是new Banana(),都會出現編譯錯誤。
理解了extends之後,再看super就很容易理解了,即我們不能確定testSuper方法的引數中的泛型是Fruit的哪個父類,因此在呼叫get方法時只能返回Object型別。結合extends可見,在獲取泛型元素時,使用extends獲取到的是泛型中的上邊界的型別(本例子中為Fruit),範圍更小。
總結:
在使用泛型時,存取元素時用super,獲取元素時,用extends
————————————————
package com.Iori; import android.app.Activity; import com.Iori.Util.CommUtil; import java.lang.ref.WeakReference; import com.Iori.IEntity; import androidx.annotation.Nullable; public abstract class CommonCallback<T extends IEntity> extends GeneralCallback<T> { protected Activity __this; public CommonCallback() { __this = (Activity) getWeakRefActivity().get(); } private boolean checkContent() { Activity activity = (Activity) getWeakRefActivity().get(); if(activity == null || activity.isFinishing()) { return false; } return true; } protected boolean isDismissLoadingDataReady() { return true; } @Override public void onDataReady(@Nullable T data) { if(checkContent() == false) return; if(isDismissLoadingDataReady()) { CommUtil.dismissHUD(); } if(data.Success) { doProcessData(data); } else { CommUtil.alert( __this, null, data.Msg); } } public abstract void doProcessData(T data); }