Java 反射概览: 泛型 Type

产生背景

泛型信息在运行时将会被擦除,Type的引入使得开发者在程序运行期内获取属性或者类的具体声明成为可能。

Type类图

«interface» Type «interface» ParameterizedType «interface» GenericArrayType «interface» TypeVariable «interface» WildcardType

ParameterizedType

英文直译为参数化类型,有的人看到参数化类型就蒙了:和泛型有什么关系?其实参数化类型就是泛型,不要被不同的翻译误导了。

参数化

理解参数化类型,先要了解参数化:

假如我有一个边长是4的正方形,计算正方形的面积:4x4 = 16。如果边长变成了3,面积就是3x3 = 9。这时候来了一个聪明人,说我们可以用a代表正方形的边长,所有正方形的面积就是a x a。不管a是多少,只要带入公式就能得到面积。用a代表边长的方式,就称为参数化,或者称为参数化边长。

再来理解参数化类型就方便了,我可以随便定义一个符号代表类型。List中用的是E,Map用的是K和V。所以参数化类型,就是我们经常使用的泛型。

public interface List<E> extends Collection<E>
public interface Map<K, V> 

然后我们看一看C类中,哪个字段的类型是ParameterizedType

 public class C {
      private List<String> list;
      private Map<String, Integer> map;
      private Class<?> aClass;
      private Bean<String> bean;
      private List list_1;

      public class Bean<T> {

      }
 }

结合对参数化的理解,C类中除了list_1,其他字段的类型都是ParameterizedType:

@Test
public void parameterizedTypeInClass(){
    Class c = C.class;
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        System.out.println(field.getName() + " is ParameterizedType : "+ (field.getGenericType() instanceof ParameterizedType));
    }
}
list is ParameterizedType : true
map is ParameterizedType : true
aClass is ParameterizedType : true
bean is ParameterizedType : true
list_1 is ParameterizedType : false

方法

Type[] getActualTypeArguments()

获取参数的实际类型,说通俗点,就是尖括号<>中的类型

public void getActualTypeArguments(){
    Class c = C.class;
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        if(field.getGenericType() instanceof ParameterizedType){
            ParameterizedType genericType = (ParameterizedType) field.getGenericType();
            System.out.println(field.getName() + " : "+ Arrays.toString(genericType.getActualTypeArguments()));
        }
    }
}
list : [class java.lang.String]
map : [class java.lang.String, class java.lang.Integer]
aClass : [?]
bean : [class java.lang.String]

Type getRawType();

返回表示声明此类型的类或接口的Type对象。简单说就是字段基本类型。

@Test
public void getRawType(){
    Class c = C.class;
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        if(field.getGenericType() instanceof ParameterizedType){
            ParameterizedType genericType = (ParameterizedType) field.getGenericType();
            System.out.println(field.getName() + " : "+ genericType.getRawType());
        }
    }
}
list : interface java.util.List
map : interface java.util.Map
aClass : class java.lang.Class
bean : class com.example.myapplication.type.TestParameterizedType$C$Bean

Type getOwnerType();

Owner的意思是拥有者。如果一个类属于其他了,会返回声明内部类的类,如果不是内部类,则返回null。

@Test
public void getOwnerType(){
    Class c = C.class;
    Field[] fields = c.getDeclaredFields();
    for (Field field : fields) {
        if(field.getGenericType() instanceof ParameterizedType){
            ParameterizedType genericType = (ParameterizedType) field.getGenericType();
            System.out.println(field.getName() + " : "+ genericType.getOwnerType());
        }
    }
}

Bean是C类中的内部类,因此Bean的拥有者Owner是C。

list : null
map : null
aClass : null
bean : class com.example.myapplication.type.TestParameterizedType$C

GenericArrayType

泛型数组

class A<T> {
    T[] arr;
}

@Test
class A<T> {
    T[] arr;
    String[] arrString;
}

@Test
public void testGeneric(){
    Class<A> aClass = A.class;
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        Type genericType = declaredField.getGenericType();
        System.out.println(declaredField.getName() + " : "+(genericType instanceof GenericArrayType));
    }

}
arr : true
arrString : false

方法

getGenericComponentType

返回数组的类型

@Test
public void getGenericComponentType(){
    Class<A> aClass = A.class;
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        Type genericType = declaredField.getGenericType();
        if (genericType instanceof GenericArrayType) {
          System.out.println("getGenericComponentType:"+((GenericArrayType) genericType).getGenericComponentType());
        }
    }
}
getGenericComponentType:T

TypeVariable

类型变量,使用泛型时,常用的大写替代字母,属于这种类型。

//B类声明了2个泛型,即两个TypeVariable
public class B<T extends String, E> {
    List<T> list;
    Map<T, E> map;
    E e;
    public E method(E e){
        return e;
    }
}
@Test
public void TypeVariable() {
    Class bClass = B.class;
    Method[] declaredMethods = bClass.getDeclaredMethods();
    for (Method declaredMethod : declaredMethods) {
        Type[] genericParameterTypes = declaredMethod.getGenericParameterTypes();
        System.out.println(Arrays.toString(genericParameterTypes));
    }
    System.out.println("--------------------------------------------");
    Field[] declaredFields = bClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        Type genericType = declaredField.getGenericType();
        System.out.println(declaredField.getName() + " : " + (genericType instanceof TypeVariable));
    }
}
[E]
--------------------------------------------
list : false
map : false
e : true

方法

getBounds()

返回表示此类型变量上限的Type对象数组。 请注意,如果没有明确声明上限,则上限为Object。

@Test
public void getBounds(){
    TypeVariable<Class<B>>[] typeParameters = B.class.getTypeParameters();
    for (TypeVariable<Class<B>> typeParameter : typeParameters) {
        System.out.println(typeParameter.getName());
        Type[] bounds = typeParameter.getBounds();
        System.out.println("bounds:"+Arrays.toString(bounds));
    }
}
T
bounds:[class java.lang.String]
E
bounds:[class java.lang.Object]

getGenericDeclaration()

返回声明此类型变量的GenericDeclaration对象
关于GenericDeclaration

@Test
public void getGenericDeclaration(){
    TypeVariable[] typeParameters = B.class.getTypeParameters();
    for (TypeVariable typeParameter : typeParameters) {
        System.out.println(typeParameter.getName());
        GenericDeclaration genericDeclaration = typeParameter.getGenericDeclaration();
        System.out.println(genericDeclaration);
    }
}
T
class com.example.myapplication.type.TestTypeVariable$B
E
class com.example.myapplication.type.TestTypeVariable$B

getName()

返回此类型变量的名称

@Test
public void getName(){
    TypeVariable[] typeParameters = B.class.getTypeParameters();
    for (TypeVariable typeParameter : typeParameters) {
        String name = typeParameter.getName();
        System.out.println(typeParameter.getName()+" getName:"+name);
    }
}
T getName:T
E getName:E

WildcardType

通配符的类型。例如? , ? extends Number ?和extends Number ,? super Integer 和?
super Integer 。

public class A {
    List<? extends String> ts;//属于WildcardType
    List<?> list;//属于WildcardType
    List<? super Integer> ins;//属于WildcardType
}
@Test
public void wildcardTypeInClass() {
    Class aClass = A.class;
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        ParameterizedType genericType = (ParameterizedType) declaredField.getGenericType();
        for (Type type1 : genericType.getActualTypeArguments()) {
            System.out.println("----------------------------------");
            System.out.println("getTypeName():  " + type1.getTypeName());
            System.out.println("is WildcardType: "+ (type1 instanceof WildcardType));
        }
    }
}
getTypeName():  ? extends java.lang.String
is WildcardType: true
----------------------------------
getTypeName():  ?
is WildcardType: true
----------------------------------
getTypeName():  ? super java.lang.Integer
is WildcardType: true

方法

WildcardType定义了两个方法

Type[] getUpperBounds();
获取类型的上边界,使用extends关键字时,传递的类型必须是指定类型的子类,指定类型即上边界,使用任何超出上边界的类型都是错误的

Type[] getLowerBounds();
获取类型的下边界,使用super关键字时,传递的类型必须是指定类型的父类,指定类型即下边界,使用任何超出下边界的类型都是错误的

@Test
public void testMethods(){
    Class aClass = A.class;
    Field[] declaredFields = aClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        ParameterizedType genericType = (ParameterizedType) declaredField.getGenericType();
        for (Type type1 : genericType.getActualTypeArguments()) {
            System.out.println("getTypeName():  " + type1.getTypeName());
            if (type1 instanceof WildcardType) {
                System.out.println("getUpperBounds(): " + Arrays.toString(((WildcardType) type1).getUpperBounds()));
                System.out.println("getLowerBounds(): " + Arrays.toString(((WildcardType) type1).getLowerBounds()));
                System.out.println("----------------------------------");
            }
        }
    }
}
getTypeName():  ? extends java.lang.String
getUpperBounds(): [class java.lang.String]
getLowerBounds(): []
----------------------------------
getTypeName():  ?
getUpperBounds(): [class java.lang.Obj	ect]
getLowerBounds(): []
----------------------------------
getTypeName():  ? super java.lang.Integer
getUpperBounds(): [class java.lang.Object]
getLowerBounds(): [class java.lang.Integer]
----------------------------------

参考资料:
java Type 详解
Java中rtti的实现–>Type类介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值