泛型擦除
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出生就具备将类型参数保存为第一类实体,便可以通过反射或执行基于类型语言的操作