泛型<?>和<T>的區別

一直以來,泛型的使用都是個迷,特別是<?>和<T>更令人疑惑
現在來揭開謎團
來看例子

/**
 只有聲明<T>才是泛型方法,其位置在修飾符和返回值之間
*/
public static <T> void show1(List<T> list){  //泛型用在方法上的寫法
 for (Object object : list) {
        System.out.println(object.toString());
    }
}

public static void show2(List<?> list) {
    for (Object object : list) {
        System.out.println(object);
    }
}

上述方法說明,泛型方法在使用時,能確定泛型是同一種,而<?>可以定義泛型是多種

public static void test(){
   List<Student> list1 = new ArrayList<>();
   list1.add(new Student("zhangsan",18,0));
   list1.add(new Student("lisi",28,0));
   list1.add(new Student("wangwu",24,1));
   //這里如果add(new Teacher(...));就會報錯,因為我們已經給List指定了數據類型為Student
   show1(list1);

   System.out.println("************分割線**************");

   //這里我們并沒有給List指定具體的數據類型,可以存放多種類型數據
   List list2 = new ArrayList<>();
   list2.add(new Student("zhaoliu",22,1));
   list2.add(new Teacher("sunba",30,0));
   show2(list2);
}

直觀感受...

泛型可用于泛型類泛型接口、泛型方法,其中泛型方法是比較難理解的...

/**
 * 泛型方法的基本介紹
 * @param tClass 傳入的泛型實參
 * @return T 返回值為T類型
 * 說明:
 *     1)public 與 返回值中間<T>非常重要,可以理解為聲明此方法為泛型方法。
 *     2)只有聲明了<T>的方法才是泛型方法,泛型類中的使用了泛型的成員方法并不是泛型方法。
 *     3)<T>表明該方法將使用泛型類型T,此時才可以在方法中使用泛型類型T。
 *     4)與泛型類的定義一樣,此處T可以隨便寫為任意標識,常見的如T、E、K、V等形式的參數常用于表示泛型。
 */
public <T> T genericMethod(Class<T> tClass)throws InstantiationException ,
  IllegalAccessException{
        T instance = tClass.newInstance();
        return instance;
}
Object obj = genericMethod(Class.forName("com.test.test"));

public class GenericFruit {
    class Fruit{
        @Override
        public String toString() {
            return "fruit";
        }
    }
    class Apple extends Fruit{
        @Override
        public String toString() {
            return "apple";
        }
    }
    class Person{
        @Override
        public String toString() {
            return "Person";
        }
    }
    class GenerateTest<T>{
        public void show_1(T t){
            System.out.println(t.toString());
        }
        //在泛型類中聲明了一個泛型方法,使用泛型E,這種泛型E可以為任意類型??梢灶愋团cT相同,也可以不同。
        //由于泛型方法在聲明的時候會聲明泛型<E>,因此即使在泛型類中并未聲明泛型,編譯器也能夠正確識別泛型方法中識別的泛型。
        public <E> void show_3(E t){
            System.out.println(t.toString());
        }
        //在泛型類中聲明了一個泛型方法,使用泛型T,注意這個T是一種全新的類型,可以與泛型類中聲明的T不是同一種類型。
        public <T> void show_2(T t){
            System.out.println(t.toString());
        }
    }
    public static void main(String[] args) {
        Apple apple = new Apple();
        Person person = new Person();

        GenerateTest<Fruit> generateTest = new GenerateTest<Fruit>();
        //apple是Fruit的子類,所以這里可以
        generateTest.show_1(apple);
        //編譯器會報錯,因為泛型類型實參指定的是Fruit,而傳入的實參類是Person
        //generateTest.show_1(person);

        //使用這兩個方法都可以成功
        generateTest.show_2(apple);
        generateTest.show_2(person);

        //使用這兩個方法也都可以成功
        generateTest.show_3(apple);
        generateTest.show_3(person);
    }
}

較為詳細的引用地址:https://www.cnblogs.com/icebutterfly/p/9012858.html

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 關于Mongodb的全面總結 MongoDB的內部構造《MongoDB The Definitive Guide》...
    中v中閱讀 32,010評論 2 89
  • 轉載自這里,這哥們也是轉載但是沒注明....所以找不到原作者 1. 概述 泛型在java中有很重要的地位,在面向對...
    琴匣自鳴閱讀 1,277評論 0 14
  • 早上走的時候孩子都不起床。早飯有時也不吃,感覺有點亂套了。這兩天都是孩爸做飯。中午炒的青豆芽,李昊在看電腦。遲...
    會飛的抱抱閱讀 233評論 0 0
  • (一) 我就覺得我是一個騎士,一個天生的騎士。 可他們都說我有病,是一個瘋子。 無所謂,我才懶得管他們,...
    abcde13579閱讀 324評論 0 3
  • 1. 有一天晚上回家,在小區門口聽到有人在大聲說,油條,油條……我非常納悶,一般來說在油條不是早點嗎,這大半夜的哪...
    子阿不語閱讀 769評論 0 0