一圖看懂Java泛型通配符

clipboard.png

當使用 <? super MyClass> 的時候,代表未知類的繼承結構處於 ObjectMyClass 之間,這時html

  • 編譯器只能肯定任何返回該未知類型的方法,返回的變量都是 Object 的子類,因此返回的類型就肯定爲 Object,好比 getter 方法
  • 使用該未知類型做爲參數的方法,該參數必定是 MyClass 的父類,因此能夠傳遞 MyClass 及其子類進去,好比 setter 方法

而使用 <? extends MyClass> 的時候,未知類型必定是 MyClass 的子類,但向下延伸到無窮盡,沒法判斷java

  • 因此返回未知類型的方法的返回類型有一個上界,就是 MyClass,即返回類型肯定爲 MyClass
  • 可是使用未知類型的方法,由於向下繼承無限延伸,沒法判斷下界,因此不能使用該方法,好比 setter(能夠 set(null))

使用 <?> 的時候,能夠看成 <? extends Object>,即上界是 Object,能夠使用 getter 方法,不能夠使用 setter 方法。spa

根據上面這些原則,一個簡單的例子以下:3d

@Data // lombok,省略了 getter 和 setter
class Holder<T>{
    private T t;

    public <U extends MyClass> void testSetter(Holder<? super MyClass> holder, U u) {
        holder.setT(u); // 能夠輸入任何 MyClass 及子類的對象
        holder.setT(null);
    }

    public  void testGetter1(Holder<? extends MyClass> holder) {
        MyClass obj = holder.getT(); // 能肯定返回的對象必定是 MyClass 或父類的對象
    }

    public void testGetter2(Holder<?> holder) {
        Object obj = holder.getT(); // 只能肯定返回的對象必定是 Object
    }
}

class MyClass{}

選擇限定通配符時的快速判斷方法:code

get-put principle:
Use an extends wildcard when you only get values out of a structure, use a super wildcard when you only put values into a structure, and don't use a wildcard when you do both.

參考:
https://www.ibm.com/developerworks/java/library/j-jtp07018/index.htmlhtm

相關文章
相關標籤/搜索