泛型

匿名 (未验证) 提交于 2019-12-03 00:00:02
public class Pair<T> { … }
public static <K> Pair<K> create(K first, K last) { … }
public class Pair<T,K> { … }

  • Java的泛型(Generic)是采用擦拭法(Type Erasure)实现的。

  • 编译把视为Object

  • 编译器根据实现安全的强制转型

      我们写的是   public static void main(String[] args) {       Pair<String> pair = new Pair<>("xiao","ming");       String first = pair.getFirst();   }    实际上编译器处理的是   public static void main(String[] args) {       Pair pair = new Pair("xiao","ming");       String first = (String)pair.getFirst();   }
  • 不能是基本类型,例如int

  • Object字段无法持有基本类型

  • 无法取得带泛型的Class(返回的永远的同一个Class) 如:Pair<String>.class

  • 无法判断带泛型类型的类型,例如:x instanceof Pair<String>

  • 不能实例化 T 类型 如:new T();

  • 可以继承自泛型类:

      public class IntPair extends Pair<Integer> {   }
  • 泛型方法要防止重复定义,例如: public boolean equals(T obj)

  • 子类可以获取父类的泛型类型。

Type
|
+- Class
|
+- ParameterizedType
|
+- GenericArrayType
|
+- WildcardType


void someMethod(List<? extends Number> list) {  Number n = list.get(0);  list.add(n); // ERROR } 允许传入List<Number>,List<Integer>,List<Double>... 允许调用方法获取Number类型 不允许调用方法传入Number类型(null除外)
定义泛型时可以通过extends限定T必须是Number或Number的子类

  • 允许传入List,List,List
  • 允许调用方法传入Integer类型 set方法
  • 不允许调用方法获取Integer类型(Object除外) get方法
    void someMethod(List<? super Integer> list) {
    list.add(123);
    Integer n = list.get(0); // ERROR
    }
  • 泛型限定为Integer或Integer的超类
  • <? extends T>允许调用方法获取T的引用

  • <? super T>允许调用方法传入T的引用

  • 只能获取Object引用

  • 只能传入null

  • 可以用消除<?>


  • Class

      Class clazz = String.class;   String str = (String) clazz.newInstance();    Class<String> clazz = String.class;   String str = clazz.newInstance();    Class<? super String> sup = clazz.getSuperclass();
  • Constructor

      Class<Integer> clazz = Integer.class();   Constructor<Integer> cons = clazz.getConstructor(int.class);   Integer i = cons.newInstance(123);
  • 可以声明带泛型的数组,但不能直接创建带泛型的数组,必须强制转型

      Pair<String> [] ps = null;                  //正确   Pair<String> [] ps = new Pair<String>[2];   //错误    @suppressWarnings("unchecked")   Pair<String>[] ps = (Pair<String>[]) new Pair[2];  //正确
    • 不安全的使用带泛型的数组:

        public static void main(String[] args) {       Pair[] arr = new Pair[2];       Pair<String>[] ps = (Pair<String>[])arr;        ps[0] = new Pair<String>("a","b");       arr[1] = new Pair<Integer>(1,2);         try {           //ClassCastException           Pair<String> p = ps[1];        } catch (Exception e) {           System.err.println(e.getMessage()); //java.lang.Integer cannot be cast to java.lang.String       }   }
    • 安全的使用带泛型的数组:

        @suppressWarnings("")   Pair<String>[] ps = (Pair<String>[]) new Pair[2]; 
    • 带泛型的数组实际上是编译器进行类型的擦除

        Pair[] arr = new Pair[2];   Pair<String>[] ps = (Pair<String>[]) arr;    System.out.println(ps.getClass()==Pair[].class);//true    String s1 = (String) arr[0].getFirst();   String s2 = ps[0].getFirst();
  • 可以通过Array.newInstance(Class, int)创建T[]数组,需要强制转型

    • 不能直接创建T[]数组,擦拭后代码变为new Object[]

        //compile error:   public class Abc<T>{       T[] createArray(){           return new T[5];       }   }
    • 借助Class

        public class Abc<T>{       T[] createArray(Class<T> cls){           return (T[])Array.newInstance(cls,5);       }   }    //使用   String[] s = new Abc<String>().createArray(String.class);
    • 利用可变参数创建T[]数组,@SafeVarargs消除编译警告

        public class ArrayHelper{       @SafeVarargs                       static <T> T[] asArray(T... objs){           return objs;       }        public static void main(String[] args) {           String[] ss = asArray("a","B","c");       }   }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!