JAVA泛型程序设计

 

类型变量使用大写形式,且比较短, 这是很常见的。在 Java 库中, 使用变量 E 表示集合的元素类型, K 和 V 分别表示表的关键字与值的类型。T ( 需要时还可以用临近的字母 U 和 S) 表示“ 任意类型”。

1.简单的泛型类

public class Pair<T> 
{
   private T first;
   private T second;

   public Pair() { first = null; second = null; }
   public Pair(T first, T second) { this.first = first;  this.second = second; }

   public T getFirst() { return first; }
   public T getSecond() { return second; }

   public void setFirst(T newValue) { first = newValue; }
   public void setSecond(T newValue) { second = newValue; }
}

2.简单的泛型方法

   public static <T> T getMiddle(T... a)
   {
      System.out.println(a.length);
      return a[a.length / 2];
   }

3.将T 限制为实现了 Comparable 接口的类,


   public static <T extends Comparable> Pair<T> minmax(T[] a)
   {
      if (a == null || a.length == 0) return null;
      T min = a[0];
      T max = a[0];
      for (int i = 1; i < a.length; i++)
      {
         if (min.compareTo(a[i]) > 0) min = a[i];
         if (max.compareTo(a[i]) < 0) max = a[i];
      }
      return new Pair<>(min, max);
   }

这里限定了 T 一定要实现Comparable接口,如果使用该方法时没有实现 Comparable 接口, 编译时将会报错。

LocalDate 有实现Comparable.

这里我自定义了一个没有实现Comparable的Pair。

一个类型变量或通配符可以有多个限定。

 例:T extends Comparable & Serializable

泛型与虚拟机

虚拟机没有泛型类型对象—所有对象都属于普通类。

无论何时定义一个泛型类型, 都自动提供了一个相应的原始类型 ( raw type )。原始类型
的名字就是删去类型参数后的泛型类型名。擦除( erased) 类型变M, 并替换为限定类型(无
限定的变量用 Object)。

 

总之,需要记住有关 Java 泛型转换的事实:
•虚拟机中没有泛型,只有普通的类和方法。
•所有的类型参数都用它们的限定类型替换。
•桥方法被合成来保持多态。
•为保持类型安全性,必要时插人强制类型转。

 

约束与局限

由于擦除的原因,泛型的使用有一些约束与局限。大部分都是应该这些阶段需要再编译期确定下来。而对于虚拟机而言,并没有所谓泛型。

  1. 不能用基本类型实例化类型参数。没有 Pair<double>, 只 有 Pair<Double>
  2. 运行时类型查询只适用于原始类型。eg: if (a instanceof Pair<String>) // Error
  3. 不能创建参数化类型的数组。 Pair<String>[] table = new Pair<String>[10]; // Error 擦除之后, table 的类型是 Pair[]。
  4. 不能实例化类型变置 不能使用像 new T(...,) newT[...] 或 T.class 这样的表达式中的类型变量。
  5. 不能构造泛型数组,数组本身也有类型,用来监控存储在虚拟机中的数组。这个类型会被擦除。eg:public static <T extends Comparable〉T[] minmax(T[] a) { T:D 刪 = new T[2]; . . . } // Error
  6. 泛型类的静态上下文中类型变量无效。 private static T singlelnstance; // Error
  7. 不能抛出或捕获泛型类的实例,甚至泛型类扩展 Throwable 都是不合法的。eg:public class Problem<T> extends Exception { /* . . . */ } // Error can't extend Throwable 

 

java泛型中的通配符 extends与super


1. ? 表示通配符类型 
2. <? extends T> 既然是extends,就是表示泛型参数类型的上界,说明参数的类型应该是T或者T的子类。 
3. <? super T> 既然是super,表示的则是类型的下界,说明参数的类型应该是T类型的父类,一直到object。

 

public class GenericClass {

    static class Animal {}

    static class FlyAnimal extends Animal {}

    static class Bird extends FlyAnimal {}

    public void testExtend() {
        List<? extends FlyAnimal> list = new ArrayList<Bird>();

        //无法安全添加任何具有实际意义的元素
        //list.add(new Bird());
        //list.add(new FlyAnimal());
        list.add(null);
        Animal animal = list.get(0);
        Bird bird = (Bird)list.get(0);
    }

    public void testSuper() {
        List<? super FlyAnimal> list = new ArrayList<FlyAnimal>();
        list.add(new FlyAnimal());
        list.add(new Bird());
        //list.add(new Animal());
        //List<? super FlyAnimal> list2 = new ArrayList<Bird>();
        //FlyAnimal flyAnimal = list.get(0); 不能确定返回类型

    }

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值