泛型

1.简单泛型类的定义
一个泛型类就是具有一个或多个类型变量的类。
例:public class Pair<T>{...}
可以有多个类型变量:public class Pair<T,U>{...}
类定义中的类型变量指定方法的返回类型以及域和局部变量的类型:private T first;
用具体的类型替换类型变量就可实例化泛型类型:Pair<String>
泛型类可看做是普通类的工厂。
2.泛型方法
例:public static <T>T getMiddle(T[] a){return a[a.length/2];}
调用一个泛型方法时,方法名前的尖括号中放入具体类型:
String middle=ArrayAlg.<String>getMiddle(names);
可以省略String类型参数:String middle=ArrayAlg.getMiddle(names);
3.类型变量的限定
例:

   public static <T extends Comparable>T min(T[] a){
      if(a==null||a.length==0)
          return null;
       T min = a[0];
       for(int i=0;i<a.length;i++)
         if(min.compareTo(a[i]>0)
             min=a[i];
       return min;
  }
  //泛型的min方法只能被实现了Comparable接口的类的数组调用。
  //限定类型用"&"分隔:<T extends Comparable&Serializable>

4.泛型代码和虚拟机
无论何时定义一个泛型类型,都自动提供了一个相应的原始类型。
原始类型用第一个限定的类型变量来替换,若没有就用Object替换。

   public class Interval<T extends Comparable&Serializable> implements Serializable{
      public Interval(T first,T second){
         if(first.compareTo(second)<=0){
            lower = first;
            upper = second;
          }
          else{
            lower = second;
            upper = first;
          }
      }
      ...
      private T lower;
      private T upper;
   }

原始类型如下:

   public class Interval implements Serializable{
      public Interval(Comparable first,Comparable second){
         if(first.compareTo(second)<=0){
            lower = first;
            upper = second;
          }
          else{
            lower = second;
            upper = first;
          }
      }
      ...
      private Comparable lower;
      private Comparable upper;
   }

4.1翻译泛型表达式
当程序调用泛型方法时,如果擦除返回类型,编译器插入强制类型转换。
例:

  Pair<Employee> buddies = ...;
  Employee buddy = buddies.getFirst();
  //擦除getFirst的返回类型后将返回Object类型。

编译器自动插入Employee的强制类型转换。编译器把这个方法调用翻译为两条虚拟机指令:
(1)对原始方法Pair.getFirst的调用;
(2)将返回的Object类型强制转换为Employee类型。
4.2翻译泛型方法
虚拟机中,用参数类型和返回类型确定一个方法。
4.3调用遗留代码
5.约束与局限性
5.1不能用基本类型实例化类型参数(因为类型擦除)Pair<double> -> Pair<Double>
5.2运行时类型查询只适应于原始类型。
getClass方法总是返回原始类型:

   Pair<String> stringPair = ...;
   Pair<Employee> employeePair = ...;
   stringPair.getClass()==employeePair.getClass();//Pair.class

5.3不能抛出也不能捕获泛型类实例
5.4不能声明参数化类型的数组

  Pair<String>[] table = new Pair<String>[10];//错误
  ArrayList<Pair<String>> = new ArrayList<Pair<String>>[10];//既安全又有效

5.5不能实例化类型变量public Pair(){first = new T();second = new T();}//错误
5.6泛型类的静态上下文中类型变量无效
不能在静态域或方法中引用类型变量。
5.7注意擦除后的冲突
6.泛型类型的继承规则

  Pair<Manager>并不是Pair<Employee>的子类,

泛型类可以扩展或实现其他的泛型类。

   ArrayList<T>可实现List<T>接口;
   ArrayList<Manager>可转换为List<Manager>

这里写图片描述
7.通配符类型

  public static void printBuddies(Pair<Employee> p){
      //不能将Pair<Manager>传递给这个方法;
      Employee first = p.getFirst();
      Employee second = p.getSecond();
      System.out.println(first.getName()+"and"+second.getName()+"are buddies";
  } 
  //使用通配符:Pair<Manager>是Pair<? extends Employee>的子类型
  public static void printBuddies(Pair<? extends Employee> p){
      //可以将Pair<Manager>传递给这个方法;
      //不能调用setFirst方法,可以调用getFirst
      //安全的访问器,不安全的更改器
      ...
  }

7.1通配符的超类型限定
? super Manager //Manager的所有超类型
与前面介绍相反,可以为方法提供参数,但不能使用返回值。

   void setFirst(**? super Manager**)
   **? super Manager** getFirst()
   //可用Manager对象(或子类型)调用setFirst,不能用Employee对象调用;
   //若调用getFirst,返回的对象类型得不到保障

!!带有超类型的通配符可以向泛型对象写入,带有子类型限定的通配符可以从泛型对象读取。
7.2无限定通配符Pair<?>
7.3通配符捕获
8.反射和泛型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值