當我們宣告乙個泛型類變數時,編譯器會用具體的型別代替泛型類的型別變數。
比如,我們有下面這些類:
package generic;
/** * @version 1.00 2004-05-10
* @author cay horstmann
*/public class pair
public pair(t first, t second)
public t getfirst()
public t getsecond()
public void setfirst(t newvalue)
public void setsecond(t newvalue)
}
package generic;
public class person
public string getname()
public void setname(string name)
@override
public string tostring()
public integer printandreturn()
}
package generic;
public class student extends person
public string getstudentnumber()
public void setstudentnumber(string studentnumber)
@override
public string tostring()
}
我們有如下宣告:
pairpersonpair;
它只能引用pair型別的的例項:
personpair = new pair(new person("li"), new person("wang")); //ok
卻不能引用pair型別的例項:
personpair = new pair(new student("li", "1"), new student("wang", "2")); //error
因為pair不是pair,也不是它的子類。
有時候,我們可能希望乙個變數既能引用pair型別的的例項,也能引用
pair型別的例項,該怎麼辦呢?這就需要用到萬用字元了。
1.萬用字元的子型別限定
下面的變數宣告:
pair<? extends person> personpair;
personpair既能引用pair型別的的例項,也能引用pair型別的例項。因為pair<? extends person>表示任何型別引數是person或其子型別的pair型別。
對personpair進行如下賦值:
personpair = new pair<>(new student("li", "1"),new student("wang", "2"));// ok
然後,我們想修改personpair的第乙個值為new student("yuncong", "3"):
我們不能向personpair中傳入值,原因已經在注釋中解釋了。/**
* error,
* setfirst方法是這個樣子的:
* void setfirst(? extends person);
* 可以向方法中傳入指定的引數型別或其子型別,
* 這個地方只知道指定的引數型別是person的子類,
* 不知道具體的指定型別是什麼,也就
* 無法斷定傳入哪種型別的引數是對的,比如person
* 有子類student,student有子類seniorstudent,
* 如果指定引數型別是seniorstudent,我們就不能把student
* 傳進去;因此無法呼叫這個方法
*/personpair.setfirst(new student("yuncong", "3")); //error
但是我們可以從personpair中取出值,原因也在注釋中給出:
/**
* ok,
* getfirst方法是這個樣子的:
* ? extends person getfirst(),
* 它返回的是person的子類,把person的子類
* 的例項賦值給person類變數完全沒有問題
*/person person = pair.getfirst(); //ok
可見,只可以從|型別變數替換為帶有子型別限定的萬用字元的|(豎線之間的是乙個長長的修飾語)泛型類物件中讀取。
2.萬用字元的超型別限定
萬用字元的超型別限定提供了與萬用字元的子型別限定相反的行為,只可以向型別變數替換為帶有超型別限定的萬用字元的泛型類物件中寫入。
假設我們宣告了這樣乙個personpair:
/**
* pair<? super student>表示引數型別為student
* 或其父類的pair型別;
* 父型別變數可以引用子型別例項
*/pair<? super student> personpair = new pair(new student("li", "1"),
new student("wang", "2"));
可以設定personpair的值:
/**
* ok,
* setfirst方法是這個樣子的:
* void setfirst(? super student);
* 因為乙個方法能接收它指定引數型別及子類型別的引數,
* 這裡只知道傳入引數是student的父類,雖然不知道具體的父類
* 是什麼,但是傳入student類及其子類的例項必定屬於student的父類
* 的子類
*/personpair.setfirst(new student("wang", "2"));//ok
但不能從personpair中讀取值(也不是完全不可以,只是得到的例項的型別得不到保證):
/**
* getfirst方法是這個樣子的:
* ? super student getfirst(),
* 只知道它的返回型別必定是student及其父類的例項,
* 但必定是object或它的子類
*/object object = personpair.getfirst();
Java泛型 自限定
public class abstractbootstrap,c extends channel 子型別b是父型別abstractbootstrap 的乙個型別引數,因此可以法返回到執行時例項的引用以支援方法的鏈式呼叫 1 自限定型別 class basicholder public void se...
泛型的限定(對泛型萬用字元的範圍進行限制)
泛型的限定。對泛型萬用字元的範圍進行限制。表示泛型的型別只能是 a類或者 a類的子類。上限,最高到a類。表示泛型的型別只能是 a類或者 a類的父類。下限,最低到a類。泛型的使用場景 一般用於後期的 重構,的優化。public classdemo02generic public static void...
Java 泛型中的萬用字元
萬用字元有 3 種形式 1 無限定萬用字元 public void testwildcards collection collection 上面的 中,方法內的引數是被無限定萬用字元修飾的 collection 物件,它隱略地表達了乙個意圖或者可以說是限定,那就是 testwidlcards 這個方...