泛型<?>和<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可以为任意类型。可以类型与T相同,也可以不同。
        //由于泛型方法在声明的时候会声明泛型<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,127评论 2 89
  • 转载自这里,这哥们也是转载但是没注明....所以找不到原作者 1. 概述 泛型在java中有很重要的地位,在面向对...
    琴匣自鸣阅读 5,037评论 0 14
  • 早上走的时候孩子都不起床。早饭有时也不吃,感觉有点乱套了。这两天都是孩爸做饭。中午炒的青豆芽,李昊在看电脑。迟...
    会飞的抱抱阅读 1,618评论 0 0
  • (一) 我就觉得我是一个骑士,一个天生的骑士。 可他们都说我有病,是一个疯子。 无所谓,我才懒得管他们,...
    abcde13579阅读 2,563评论 0 3
  • 1. 有一天晚上回家,在小区门口听到有人在大声说,油条,油条……我非常纳闷,一般来说在油条不是早点吗,这大半夜的哪...
    子阿不语阅读 4,079评论 0 0