泛型擦除
class Foo{}class Goo{}class SupFoo extends Foo{};public class ErazeTypeEquivalence {public static void main(String[] args) {Class c1 = new ArrayList<String>().getClass();Class c2 = new ArrayList<Integer>().getClass();System.out.println(c1);System.out.println(c1 == c2);//此时list中该添加什么类型的数据?或者如何添加数据❓List<? extends Foo> list = new ArrayList<>();Class listClass = list.getClass();System.out.println(listClass == c2);}}
关于泛型擦除的理解:
1,在泛型代码内部,无法获得任何泛型参数的类型信息
2,无法知道用来创建某个特定实例的实例的类型参数
3,使用泛型时,关于类型参数被Java擦除,唯一知道的是你在使用一个对象
import java.util.*;class Frob {}class Fnorkle {}class Quark<T> {}class Particle<P,M> {}public class LostInformation {public static void main(String[] args) {List<Frob> list = new ArrayList<Frob>();Map<Frob,Fnorkle> map = new HashMap<Frob,Fnorkle>();Quark<Fnorkle> quark = new Quark<Fnorkle>();Particle<Long,Double> p = new Particle<Long,Double>();System.out.println(Arrays.toString(list.getClass().getTypeParameters()));System.out.println(Arrays.toString(map.getClass().getTypeParameters()));System.out.println(Arrays.toString(quark.getClass().getTypeParameters()));System.out.println(Arrays.toString(p.getClass().getTypeParameters()));}}
如何通过泛型使用某一类型的方法?
边界使用方式1,
问题:public class HasF {public void f(){System.out.println("HasF.f() ");}}class Manipulator<T>{private T o;public Manipulator(T o){this.o = o;}public void manipulate(){o.f();//Cannot resolve method 'f' in 'T'}}public class Manipulation {public static void main(String[] args) {}}
解决方案:使用边界通过extends来限定边界class Manipulator<T extends HasF>{private T o;public Manipulator(T o){this.o = o;}public void manipulate(){o.f();}}public class Manipulation {public static void main(String[] args) {HasF f = new HasF();Manipulator<HasF> manipulator = new Manipulator<HasF>(f);manipulator.manipulate();//此时依然有类型擦除System.out.println(Arrays.toString(manipulator.getClass().getTypeParameters()));}}
边界使用方式2<br />可以返回Woo及其子类,但不需要显示的类型转换
class Woo{}
class Xoo extends Woo{}
public class GenericBoundaryApp<T extends Woo> {
private T t;
GenericBoundaryApp(T t){
this.t= t;
}
public T getT(){
return t;
}
public static void main(String[] args) {
final GenericBoundaryApp<Woo> app1 = new GenericBoundaryApp<Woo>(new Woo());
System.out.println(Arrays.toString(app1.getClass().getTypeParameters()));
final Woo woo = app1.getT();
System.out.println(woo);
final GenericBoundaryApp<Xoo> app2 = new GenericBoundaryApp<>(new Xoo());
System.out.println(Arrays.toString(app2.getClass().getTypeParameters()));
final Xoo x = app2.getT();
System.out.println(x);
//依然无法获得类型参数
System.out.println(app1.getClass() == app2.getClass());
}
}
理解泛型擦除
语言本身没有该特性
折中——擦除,代价【无法获得类型参数的类型信息,无法执行基于类型语言的操作】
Java出生就具备将类型参数保存为第一类实体,便可以通过反射或执行基于类型语言的操作
