GeorgeYang'Blog

my technology blog

[笔记]java高级泛型编程

阅读:682 创建时间:17-01-13 23:46:02 tags:java

  • 泛型的信息擦除

Java泛型编程时,编译器忽略泛型参数的具体类型,认为使用泛型的类、方法对Object都适用,这在泛型编程中称为类型信息檫除。 例如:

 class GenericType{  
     public static void main(String[] args){  
         System.out.println(new ArrayList<String>().getClass());  
         System.out.println(new ArrayList<Integer>().getClass());  
     }
 }

输出结果为: java.util.ArrayList java.util.ArrayList 泛型忽略了集合容器中具体的类型,这就是类型檫除。

  • 泛型边界

Java泛型编程中使用extends关键字指定泛型参数类型的上边界(使用super关键字指定泛型的下边界),即泛型只能适用于extends关键字后面类或接口的子类。 Java泛型编程的边界可以是多个,使用如

 <T extends A & B & C>

语法来声明,其中只能有一个是类,并且只能是extends后面的第一个为类,其他的均只能为接口(和类/接口中的extends意义不同)。 使用了泛型边界之后,泛型对象就可以使用边界对象中公共的成员变量和方法。

 泛型的上边界
 public static <T extends Comparable> T min(T[] a){......}

 泛型的下边界
 private <T> void writeWithWildcards(List<? super T> list, T item){...}

如果要求泛型的实现中实现多个方法,就用extends 多个接口或类,中间用 & 符号隔开。

 public static <T extends Comparable & Serializable, U extends Runnable> T foo(T a, U b){ 
 ...
 }


 同时实现interface1、interface2、interface3接口:
 public static <T extends SomeClass & interface1 & interface2 & interface3> T foo(T a) {
 ...
 }
  • 注:通配符”?”出现的原因 泛型初始化过程中,一旦给定了参数类型之后,参数类型就会被限制,无法随着复制的类型而动态改变,如:

    class Fruit{
    }
    class Apple extends Fruit{
    }
    class Jonathan extends Apple{
    }
    class Orange extends Fruit{
    }
    //如果使用数组:
    public class ConvariantArrays{
    Fruit fruit = new Apple[10];
    Fruit[0] = new Apple();
    Fruit[1] = new Jonathan();
    try{
    fruit[0] = new Fruit();
    }catch(Exception e){
    System.out.println(e);
    }
    try{
    fruit[0] = new Orange();
    }catch(Exception e){
    System.out.println(e);
    }
    }

编译时没有任何错误,运行时会报如下异常:

java.lang.ArrayStoreException:Fruit

java.lang.ArrayStoreException:Orange

为了防止泛型在数组里容易出现异常问题,推荐改成集合容器类:

 public class NonConvariantGenerics{  
     List<? extends Fruit> flist = new ArrayList<Apple>();  
 }

使用?通配符指定类型必须是集成fruit的,first取出的便是fruit实例,而不是apple。

参考: link link