泛型擦除

    1. class Foo{}
    2. class Goo{}
    3. class SupFoo extends Foo{};
    4. public class ErazeTypeEquivalence {
    5. public static void main(String[] args) {
    6. Class c1 = new ArrayList<String>().getClass();
    7. Class c2 = new ArrayList<Integer>().getClass();
    8. System.out.println(c1);
    9. System.out.println(c1 == c2);
    10. //此时list中该添加什么类型的数据?或者如何添加数据❓
    11. List<? extends Foo> list = new ArrayList<>();
    12. Class listClass = list.getClass();
    13. System.out.println(listClass == c2);
    14. }
    15. }

    关于泛型擦除的理解:
    1,在泛型代码内部,无法获得任何泛型参数的类型信息
    2,无法知道用来创建某个特定实例的实例的类型参数
    3,使用泛型时,关于类型参数被Java擦除,唯一知道的是你在使用一个对象

    1. import java.util.*;
    2. class Frob {}
    3. class Fnorkle {}
    4. class Quark<T> {}
    5. class Particle<P,M> {}
    6. public class LostInformation {
    7. public static void main(String[] args) {
    8. List<Frob> list = new ArrayList<Frob>();
    9. Map<Frob,Fnorkle> map = new HashMap<Frob,Fnorkle>();
    10. Quark<Fnorkle> quark = new Quark<Fnorkle>();
    11. Particle<Long,Double> p = new Particle<Long,Double>();
    12. System.out.println(Arrays.toString(list.getClass().getTypeParameters()));
    13. System.out.println(Arrays.toString(map.getClass().getTypeParameters()));
    14. System.out.println(Arrays.toString(quark.getClass().getTypeParameters()));
    15. System.out.println(Arrays.toString(p.getClass().getTypeParameters()));
    16. }
    17. }

    如何通过泛型使用某一类型的方法?
    边界使用方式1,

    1. 问题:
    2. public class HasF {
    3. public void f(){
    4. System.out.println("HasF.f() ");
    5. }
    6. }
    7. class Manipulator<T>{
    8. private T o;
    9. public Manipulator(T o){
    10. this.o = o;
    11. }
    12. public void manipulate(){
    13. o.f();//Cannot resolve method 'f' in 'T'
    14. }
    15. }
    16. public class Manipulation {
    17. public static void main(String[] args) {
    18. }
    19. }
    1. 解决方案:使用边界
    2. 通过extends来限定边界
    3. class Manipulator<T extends HasF>{
    4. private T o;
    5. public Manipulator(T o){
    6. this.o = o;
    7. }
    8. public void manipulate(){
    9. o.f();
    10. }
    11. }
    12. public class Manipulation {
    13. public static void main(String[] args) {
    14. HasF f = new HasF();
    15. Manipulator<HasF> manipulator = new Manipulator<HasF>(f);
    16. manipulator.manipulate();
    17. //此时依然有类型擦除
    18. System.out.println(Arrays.toString(manipulator.getClass().getTypeParameters()));
    19. }
    20. }
    1. 边界使用方式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出生就具备将类型参数保存为第一类实体,便可以通过反射或执行基于类型语言的操作