java泛型類的繼承規則


首先看一看java泛型類的使用:

/**
 * 一個泛型方法:使程序更加安全
 * 並且能被更多的使用
 * @author 丁**
 *
 * @param <T>
 */
class Pair<T>{
    private T first;
    private T second;
    
    //實例化類型變量
    public static<T> Pair<T> makePair(Class<T> cl){
        try {
            return new Pair<>(cl.newInstance(), cl.newInstance());
        } catch (Exception e) {
            return null;
        } 
    }
    
    public Pair(){ first = null; second = null; }
    public Pair(T first, T second){ this.first = first; this.second = second;}
    
    public T getFirst() {
        return first;
    }
    public void setFirst(T first) {
        this.first = first;
    }
    public T getSecond() {
        return second;
    }
    public void setSecond(T second) {
        this.second = second;
    }
    
}
class Father {
    private int age = 40;
    public void getName(){
        System.out.println(age);
    }
}


class Son extends Father{
    private int age = 12;
    public void getName() {
        System.out.println(age);
    }
}

 在普通類中:Father aa = new Son();父類是可以用來指向子類的

但是在泛型類中卻不是如此:

Pair<Son> bb = new Pair<>();
Pair<Father> cc = bb;//error

1:雖然Son是Father的子類,但是Pair<T>之間沒有繼承關系:

 

List<Object> a1 = new ArrayList<>();
List<String> a2 = new ArrayList<>();
//設a1可以等於a2
//a1 = a2;
//a1.add(1111);因為是對a1進行操作,所以可以添加Object,a1.add(Object ad);
//a2.get(0);報錯,因為a1添加Object進入了a2的空間中,但是a2是String類型,所以報錯

 

2:可以將參數化類型轉換成一個原始類型:

List<String> a2 = new ArrayList<>();
List a3 = a2;//可以通過編譯,但是后面使用方法時可能會產生類型錯誤!
//這時候a3對象時原始類型,所以add(Object obj);
a3.add(123);//是對a3進行操作,但是最終結果保存到了a2中,將一個Integer裝入String中
顯然是錯誤的;

 

 

3:泛型類可以擴展或實現其他的泛型類:

//泛型接口
interface List1<E>{
}

//實現了泛型接口的泛型類
class List2<T, E> implements List1<E>{
    
}

//泛型類
class List3<T>{
    
}

//繼承了其他泛型類的泛型類
class List4<T, E> extends List3<E>{
    
}
List1<Father> b1 = new List2<Son, Father>();//因為List2實現了List1
List3<Father> b2 = new List4<Son, Father>();//List4繼承了List3,所以List3是父類,可以指向子類對象。

雖然這樣也完成了泛型類的繼承,實現了和普通類一樣的多態,但是使用起來並不是特別好,就這樣java引入了通配符概念:

通配符上限:

/* 通配符的上限:Pair<? extends Father> c2
extends是關鍵字
Pair<T>代表的是某個唯一(具體的泛型類)的泛型類:比如Pair<Son>,Pair<Father>
但是Pair<? extends Father>不是具體的泛型類,它所指的是參數類型為Father的子類的所有泛型類(包括Father)    
*/
Pair<? extends Father> c3;
Pair<Father> c1 = new Pair<>();
Pair<Son> c2 = new Pair<>();
//c2 = c1;error
c3 = c1;
c3 = c2;

 需要注意的是:

/*
* 使用通配符的上限的問題: 
* ? extends Father getFirst();
* void setFirst(? extends Father);
* 當c2= c1時:
* c2.setFirst(Father father);時,會將Father對象添加到Son對象內存中,這是不好的
* 所以使用extends上限時,不能使用setFirst(? extends Father),add(? extends Father)* 等方法。
* 但可以使用getFirst();方法
*/
c2.setFirst( new Father(); );//error

 通配符下限:

 

/*
* 通配符的下限:
* ? super Son
* 表示的不是某個具體的泛型類,而是表示參數類型為Son的父類的所有可能的泛型類(包括* * Son)
* 和通配符上限一樣,通配符的超類型限定不能使用getFirst()方法,但可以使用setFirst(XX)方法
*/ Pair<Son> c1 = new Pair<>(); Pair<? super Son> c3; c3 = c1;

//另一種超類型限定的寫法
Pair<T extends Comparable<? super T>> c4;

 

 

 

 無限定通配符:

 

//無限定通配符
Pair<Son> c7 = new Pair<>();
Pair<String> c5 = new Pair<>();
//c7 = c5;error,因為他們不是同一種類型
Pair<?> c6 = new Pair<>();
c6 = c5;//Pair<?>是所有的Pair泛型類的父類,Pair<?> c6 = new Pair<xx>();

 

Pair<?>和Pair的本質不同在於:可以用任意的Object對象調用原始的Pair類的setObject()方法;

通配符的捕獲:

//交換First,Second變量值
    public static void swap(Pair<?> p){
        ? t = p.getFirst();//error,因為通配符(?)不是類型變量,所以不能直接將?寫入代碼中,利用通配符的捕獲來解決這個問題。
        p.setFirst(p.getSecond());
        p.setSecond(t);
    }
//交換First,Second變量值
    public static void swap(Pair<?> p){
        swapHelper(p);//在調用下面的方法時,類型參數就被捕獲了。
    }

    //利用通配符的捕獲來解決該問題
    public static <T> void swapHelper(Pair<T> p){
        T t = p.getFirst();//T是具體的某個類型。
        p.setFirst(p.getSecond());
        p.setSecond(t);
    }

注意:通配符的捕獲只有在許多限制的情況下才是合法的,編譯器必須能夠確信通配符表達的是單個,確定的類型。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM