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"); } }
来源:博客园
作者:Rogers_Ma
链接:https://www.cnblogs.com/rogersma/p/11495132.html