# 泛型

  • 本质: 类型参数化

# 类型擦除

  • java的泛型在编译期间会被檫掉
    1. 如何保证类型安全: java编译器先检查泛型类型,再进行类型擦除,最后进行编译
    2. 类型擦除与多态冲突解决方法: 桥方法 (子类继承父类的泛型方法,本应该重写,由于类型擦除,变为了重载)

# 桥方法

class A<T>{
    void setValue(T param);
    T getValue();
}

class B extends A<String>{
    void setValue(String param);
    String getValue();
}

class A_compilied{
    void setValue(Object param);
    Object getValue();
}

//编译后的方法
class B_comiplied extends A_compilied{
    void setValue(String param);
    String getValue();

    //桥方法
    void setValue(Object param){
        setValue((String)param);
    }
    //直接写代码时,不能仅靠返回值区分函数,编译不通过。 但是编译器本身可以处理这种情况
    //协变返回类型
    Object getValue(){
        getValue();
    }   
    
}

class Test{
    public static void main(String[] args) {
            //解决多态冲突的问题
            A a = new B();
            a.setValue("aaa");
            System.out.println(a.getValue());
            
            //正常调用
            B b = new B();
            b.setValue("ccc");
            b.getValue();
    }
}

# 泛型的好处

  • 类型安全
  • 消除强制类型转换

# 获取泛型类型

  1. 将 类(Type) 强转 为 ParameterizedType
  2. 调用反射获取泛型类型数组,getActualArgumentsArgs();
  3. 只能通过对象反射获取泛型类型。 无法直接通过类获取到反射信息.
public class GetTTest {

    public static void main(String[] args) {
        //报错,因为获取到的父类Type为 Object,无法强转
//        A a = new A();
//        System.out.println(a.getTType());

//        B b = new B();
//        System.out.println(b.getTType());

        Type type = C.class;
        ParameterizedType parameterizedType = (ParameterizedType) type;
        Type[] types = parameterizedType.getActualTypeArguments();
        for (Type type1 : types) {
            System.out.println(type1);
        }

//        C c = new C();
//        System.out.println(c.getTType());


    }

    public  static class A<T>{

        public Class<T> getTType(){
            Type type =getClass().getGenericSuperclass();

            ParameterizedType parameterizedType = (ParameterizedType) type;

            Type[] types= parameterizedType.getActualTypeArguments();

            for (Type type1 : types) {
                System.out.println(type1);
            }
            return (Class<T>) types[0];
        }
    }

    public static class B extends A<Integer>{

    }

    public static class C<T> extends A<T>{

    }
}