菜鸟程序猿之浅谈泛型

一、泛型
1.1泛型的概述:
Java5开始新特性,表示不确定的类型。
分类:集合泛型和自定义泛型
注意:泛型是提供javac(编译器)使用的,它用于限定集合中的输入类型,让编译器在源码级别上,
挡住向集合中添加的非法数据。但是编译器编译完之后,带有泛型的程序,生成的.class字节码文件中将
不存在泛型。以此使程序在运行时效率不受影响,这个过程被称为泛型“擦除”。
1.2、集合泛型

集合泛型可以两边都没有,也可以一边有一边没有;可以两边都有,一旦两边都有的,两边"必须一致"(泛型没有继承关系)。List<? extends Person> list = new ArrayList<Teacher>();

1.3.自定义泛型
分为:定义在方法上和定义在类上泛型。
1.3.1定义在方法上的泛型。
 注意:
 1、泛型需要先定义再使用,方法上泛型需要定义在"返回值类型或void"的前面,通常使用一个大写的英文字母
(sun公司推荐使用T),也可以任意的英文字母,但是不要使用java中关键字和常用类(String)。
   public <T> T kill(T t){
       System.out.println("t="+t);
       return t;
   }
2、定义在方法上的泛型,只能在当前方法内部使用。
   public <T> T kill(T t){
       System.out.println("t="+t);
       return t;
   }
   public T save(T t){//出错。
       System.out.println("t="+t);
       return t;
   }
   在save方法上使用kill方法上定义的泛型T,用不了。
如果在save方法上也想泛型,需要重新定义。
   public <T> T save(T t){
       System.out.println("t="+t);
       return t;
   }
  kill和save方法中的泛型T不是同一个T:
God g = new God();
Person p = g.kill(new Person());
Dog d = g.save(new Dog());

1.3.2类上的泛型!!!
 1、定义在类上的泛型在当前类中有效,它的作用范围:在当前类的内部。
 2、泛型需要先定义再使用,类上的泛型在类名的后面定义。通常大写英文字母。
 3、类型定义的泛型在创建对象/引用时需要明确的指定泛型的具体类型。
     List<String> list = new ArrayList<String>();
 4、在类上定义的泛型不能再该类的静态方法上使用,如果想在静态方法上使用,需要单独定义。
   public static <T> T sleep(T t){
     System.out.println("t="+t);
     return t;
   }
  注意:静态方法上的T和类型的泛型T不是同一个T。
 5、无论类上或者方法上,泛型可以同时定义多个
 public class HashMap<K,V>

 6.在3的基础上,如果在创建对象时没有指定对应的类型,默认是任意类型或上边界类型
 God<T>
    God g = new God();//默认可以是任意类型
God<T extends Person>
    God g = new God();//默认上边界类型。

1.3.3泛型的通配符 !!
 void print(Collection<String> c){//Collection<?> (collection of unknown)
 }
 不支持其他泛型类型。
 为何要设计通配符?
  List<Object> list5 = new ArrayList<String>();//错误的
  因为泛型没有继承概念,所以当需要使用一个“泛型引用”引用不同的泛型实现时,写他们的共同
的父类(Object)是行不通,这是该怎么?引入了一个新的概念,就是泛型的通配符“?”,注意:
泛型的通配符只能用在泛型引用中,用来引用不同的泛型实现。
 void print(Collection<?> c){//Collection<?> (collection of unknown)
     for(Object obj:c){
    System.out.println(c);
     }
 }
 这种方式下需要注意:由于print方法参数c的类型是 Collection<?>,表示是一种不确定的类型,因此
 在print方法中不能调用和类型有关的方法。

总结:使用?通配符主要用于引用对象,使用了?通配符,就只能调用对象与类型无关的方法,不能调用
和类型有关的方法。

泛型边界:
     如果没有指定泛型的默认类型,可以接受任意的类型。
 有时希望进一步限制,需要使用泛型的边界:
     |-限定通配符的上边界!!:
        extends 用来指定泛型的上边界,在泛型定义时,通常和泛型的通配符一起使用,指定具体的
    泛型实现必须是指定类或指定类后代类。
    ArrayList<? extends Number> v1 = new ArrayList<Integer>();//正确:Integer extends Number
    ArrayList<? extends Number> v2 = new ArrayList<String>();//错误的,String类不是Number类后代类

!super - 用来指定泛型的下边界,使用在泛型的通配符中,指定具体的泛型实现必须是指定类或其超类.
    好处是,可以传入对象时,可以传入下边界的子孙类对象
    坏处是,获取到泛型对象时,只能调用Object身上的方法
//-泛型的下边界,用来指定泛型是某个类型或其祖先类型(超类),
//好处是,可以传入指定类的子孙对象,坏处是获取出来后只能当作Object使用
List<? super Person>list2 = null;
list2 = new ArrayList<Ani>();
list2.add(new Person());
list2.add(new Teacher());


猜你喜欢

转载自blog.csdn.net/yxh13521338301/article/details/80640853