T和?的區別

qq_33296156發表於2018-09-05

Java中的Object、T(泛型)、?區別

因為最近重新看了泛型,又看了些反射,導致我對Object、T(以下代指泛型)、?產生了疑惑。

我們先來試著理解一下Object類,學習Java的應該都知道Object是所有類的父類,注意:那麼這就意味著它的範圍非常廣!首先記住這點,如果你的引數型別時Object,那麼的引數型別將非常廣!

《Thinking in Java》中說很多原因促成了泛型的出現,最引人注目的一個原因就是為了創造容器類。這個要怎麼來理解呢?我的理解是,可以拋開這個為了創造容器類這個,而是回到泛型的目的是限定某種型別上來。

所以我們現在能小結一下Object和T很重要的兩點區別就是:

  1. Object範圍非常廣,而T從一開始就會限定這個型別(包括它可以限定型別為Object)。
  2. Object由於它是所有類的父類,所以會強制型別轉換,而T從一開始在編碼時(注意是在寫程式碼時)就限定了某種具體型別,所以它不用強制型別轉換。(之所以要強調在寫程式碼時是因為泛型在虛擬機器中會被JVM擦除掉它的具體型別資訊,這點可參考泛型,在這裡不做引申)。

比如在jdk中的List類是個泛型類。現在我們制定它的型別是Object。

        List<Object> list = new ArrayList<Object>();
        int i = 0;
        String s = "s";
        list.add(i);
        list.add(s);

List本身是個泛型類,現在我們指定它接收Object型別的引數,此時就可以放置任意型別的引數進去,而在取出來是就必須得進行強制型別轉換成具體的型別。

現在我們如果將List指定接收String型別的引數,那麼這個List就只能放置String型別,且取出來時就不用進行強制型別轉換。

這點給我們帶來的啟示是,在編寫類似List類的時候,一定要注意是否用泛型。一定要多寫幾個泛型類,多討論多理解,不然還是可能會攪在一起。


 接著是?,這個可能在用到反射需要獲取Class型別時用到,它的解釋就是:接收一個不確定的型別,有點和Object一樣。我對它一個理解是,如果只用"?"那麼它和Object是一樣的,但是"?"有比Object稍微“高階”有點的用法,就是它能縮小一個不確定的範圍,利用類似"? extends Test",這就意味著只接收接收Test類的繼承類,是不是比Object的範圍縮小了?

以上就是Object、T、?的區別。多寫幾行程式碼,多做試驗,多討論,就知道在何時何地恰當的使用了。

 

Class<T>和Class<?>有什麼區別

平時看java原始碼的時候,如果碰到泛型的話,我想? T K V E這些是經常出現的,但是有時想不起來代表什麼意思,今天整理下: 

? 表示不確定的java型別。
T  表示java型別。
K V 分別代表java鍵值中的Key Value。
E 代表Element。 

Object跟這些東西代表的java型別有啥區別呢?
Object是所有類的根類,是具體的一個類,使用的時候可能是需要型別強制轉換的,但是用T ?等這些的話,在實際用之前型別就已經確定了,不需要強制轉換。

追問:

也就是說,這個方法能知道返回的是哪種型別(父類),就用T行了?如果完全不知道的就用?用T的得到的物件就不需要型別轉換了,而用?的就必需用強轉了!

追答:

第一種是固定的一種泛型,第二種是隻要是Object類的子類都可以,換言之,任何類都可以,因為Object是所有類的根基類
固定的泛型指型別是固定的,比如:Interge,String. 就是<T extends Collection>

<? extends Collection> 這裡?代表一個未知的型別,
但是,這個未知的型別實際上是Collection的一個子類,Collection是這個萬用字元的上限.
舉個例子
class Test <T extends Collection> { }

<T extends Collection>其中,限定了構造此類例項的時候T是一個確定型別(具體型別),這個型別實現了Collection介面,
但是實現 Collection介面的類很多很多,如果針對每一種都要寫出具體的子類型別,那也太麻煩了,乾脆還不如用
Object通用一下。
<? extends Collection>其中,?是一個未知型別,是一個萬用字元泛型,這個型別是實現Collection介面即可。

_________________________上面講的是什麼鬼,當你知道引入萬用字元泛型的由來之後(下面程式碼由java1234.com提供)_________________________________________________________________________________________

The method take(Animal) in the type Test is not applicable for the arguments (Demo<Dog>)
The method take(Animal) in the type Test is not applicable for the arguments (Demo<Cat>)
The method take(Animal) in the type Test is not applicable for the arguments (Demo<Animal>)

當引入泛型之後,遇到這種情況,引數怎麼寫都不適合,總有2個方法不適用,為了給泛型類寫一個通用的方法,這時候就需要引入了 ?萬用字元的概念。



 

 

public class Demo <T extends Animal>{

    private T ob;

    public T getOb() {
        return ob;
    }

    public void setOb(T ob) {
        this.ob = ob;
    }

    public Demo(T ob) {
        super();
        this.ob = ob;
    }
    
    public void print(){
        System.out.println("T的型別是:"+ob.getClass().getName());
    }
}

 

相關文章