泛型類型的子類及通配符的使用

字號(hào):

本文講述以下幾個(gè)方面的內(nèi)容,試圖說明泛型類型的子類及通配符的使用。
    (1) 子類及替換原則;
    (2) 使用extends關(guān)鍵字的通配符;
    (3) 使用super關(guān)鍵字的通配符;
    (1) 子類及替換原則
    在java語言中,我們通俗講一個(gè)類是另一個(gè)類的子類型,是通過使用extends關(guān)鍵字去繼承某一個(gè)類或者使用implements關(guān)鍵字去實(shí)現(xiàn)某些接口。這樣我們?cè)诰幊虝r(shí)就可以面向接口或基類進(jìn)行編程,如:
    Number num1 = new Integer(1);
    Number num2 = new Double(2.1d);
    這個(gè)就是所謂的替換原則,替換原則的定義是:
    Substitution Principle: a variable of a given type may be assigned a value of any subtype of that type, and a method with a parameter of a given type may be invoked with an argument of any subtype of that type.
    大概的意思是說某種類型的變量可以被該類型的任何子類所賦值,一個(gè)方法中的參數(shù)也可以被該參數(shù)的任何子類進(jìn)行調(diào)用。
    現(xiàn)在我們?cè)賮砜纯捶盒椭刑鎿Q原則的適用性:
    Example2.1
    List listNums = new ArrayList();
    nums.add(10);
    nums.add(8.88);
    在example2.1 中,可以看出替換原則被很好地應(yīng)用在這里,ArrayList是List的子類,我們提供給listNums變量的類型參數(shù)為Number,往 listNums中添加元素時(shí),10被封箱為Integer類型,而Integer是Number的子類,第三行的情況類似。
    Example2.2
    List intList = new ArrayList();
    List numList = intList; //compile error
    …
    numList.add(1.35); // can‘t do that
    根據(jù)替換原則,我們會(huì)很容易想到,既然Integer是Number的子類,則我們應(yīng)該可以將List的變量賦給 List的變量,但從實(shí)際情況表明,List并不是List的子類。
    我們不妨試想想,若果List類型的變量可以成功賦值給List類型的變量,會(huì)出現(xiàn)什么情況?我們可能在程序的某個(gè)位置添加一個(gè)double類型的元素進(jìn)去numList中,而實(shí)質(zhì)上在numList中其它元素都是Integer 的類型的元素,這樣就違背了泛型的初衷了。
    有時(shí),我們確實(shí)希望將形如List的List對(duì)象賦給List的變量,這時(shí)就要使用extends關(guān)鍵字的通配符。
    (2) 使用extends關(guān)鍵字的通配符
    Example2.3
    List intList = new ArrayList();
    List<? extends Number> numList = intList();
    …
    numList.add(1.35); //compile error (can‘t do that)
    從Example2.3看到numList這個(gè)變量,我們可以將類型參數(shù)為Number及其Number子類的List賦給它。
    記住一條規(guī)則如果你使用了“? extends T”,一般情況下,你不能往該數(shù)據(jù)結(jié)構(gòu)中put元素,而你可以做的就是get元素。
    如果要往內(nèi)put元素,就需要使用下面提到的super關(guān)鍵字的通配符。
    (3) 使用super關(guān)鍵字的通配符
    Example2.4
    List intList = new ArrayList    List<? super Integer> numList = intList;
    numList.add(3); //can put integer or null
    在example2.4 我們可以看到<? super Integer>的意思為,我們可以將類型參數(shù)為Integer或Integer超類的List賦給 numList變量,并且可以put元素到列表中(注意:在該例子中put進(jìn)的元素只能為Integer或null類型)。
    一條比較通用的規(guī)則:如果要往List中put元素則用<? super T>,如果要從List中g(shù)et元素則用<? extends T>,如果既要get又要put則不使用通配符。