Java基础(反射补充)

ParameterizedType 接口

ParameterizedType 接口声明了三个方法。

  • Type[] getActualTypeArguments()
  • Type getRawType()
  • Type getOwnerType()
//例1
public class test {
    class ParameterizedClass {
        List list1;
        List<Integer> list2;
        Map map1;
        Map<String, Integer> map2;
        Map.Entry<String, Long> map3;
        List<Map<String,Integer>> map4;
    }
    public static void main(String[] args) {
        Field[] fields = ParameterizedClass.class.getDeclaredFields();
        for (Field f : fields) {
            if (f.getGenericType() instanceof ParameterizedType) {
                ParameterizedType pType = (ParameterizedType) f.getGenericType();
                System.out.println("<!---"+ pType.getTypeName()+"---!>");
                System.out.println("RawType: "+pType.getRawType().getTypeName());
                Type ownerType = pType.getOwnerType();
                if(ownerType == null){
                    System.out.println("OwnerType: Null");
                }else{
                    System.out.println("OwnerType: "+ ownerType.getTypeName());
                }
                Type[] types = pType.getActualTypeArguments();
                for (Type t : types) {
                    System.out.println("--->ActualTypeArguments:" + t.getTypeName());
                }
            }else{
                System.out.println("<!---" + f.getType() + "---!>");
            }
            System.out.println();
        }
    }
}

返回如下:

<!---interface java.util.List---!>

<!---java.util.List<java.lang.Integer>---!>
RawType: java.util.List
OwnerType: Null
--->ActualTypeArguments:java.lang.Integer

<!---interface java.util.Map---!>

<!---java.util.Map<java.lang.String, java.lang.Integer>---!>
RawType: java.util.Map
OwnerType: Null
--->ActualTypeArguments:java.lang.String
--->ActualTypeArguments:java.lang.Integer

<!---java.util.Map$Entry<java.lang.String, java.lang.Long>---!>
RawType: java.util.Map$Entry
OwnerType: java.util.Map
--->ActualTypeArguments:java.lang.String
--->ActualTypeArguments:java.lang.Long

<!---java.util.List<java.util.Map<java.lang.String, java.lang.Integer>>---!>
RawType: java.util.List
OwnerType: Null
--->ActualTypeArguments:java.util.Map<java.lang.String, java.lang.Integer>

<!---class test---!>
//例2
public class test2 {
    private static List<Map<String,Integer>> mapList;
    public static void main(String[] args) throws Exception{
        Field field = test2.class.getDeclaredField("mapList");
        System.out.println("<!---- " + field.getName() + "----!>");
        ParameterizedType fParaType = (ParameterizedType) field.getGenericType();
        System.out.println("GenericType: " + fParaType.getTypeName());
        ParameterizedType pParaType = (ParameterizedType)fParaType.getActualTypeArguments()[0];
        System.out.println("Generic -> Arguments: " + pParaType.getTypeName());
        Type[] mapArgTypes = pParaType.getActualTypeArguments();
        Class<?> mapArgType1 = (Class<?>)mapArgTypes[0];
        System.out.println("Generic -> Arguments -> ArgumentsType1: " + mapArgType1.getTypeName());
        Class<?> mapArgType2 = (Class<?>)mapArgTypes[1];
        System.out.println("Generic -> Arguments -> ArgumentsType2: " + mapArgType2.getTypeName());
    }
}

返回如下:

<!---- mapList----!>
GenericType: java.util.List<java.util.Map<java.lang.String, java.lang.Integer>>
Generic -> Arguments: java.util.Map<java.lang.String, java.lang.Integer>
Generic -> Arguments -> ArgumentsType1: java.lang.String
Generic -> Arguments -> ArgumentsType2: java.lang.Integer

由于Java类型擦除的原因,只有编译时确定的成员变量的泛型信息会被完整保留。临时创建的变量无法储存泛型信息,因此也获取不到。

WildcardType 接口

  • Type[] getUpperBounds()
  • Type[] getLowerBounds()

用于获取类在关系中的上界和下界。

其中 extends 是上界通配符,super 是下界通配符。? super classA 表示这个类是 classA 的父类。但不确定是哪个。因此处理时转到上界 Object,会失去很多信息。? extends classB 表示这个类是 classB的子类,但是classB的子类有多种的情况下,可能会获取错误的对象。

public class test3 {
    class plant{
    }
    class fruit extends plant{
    }
    class apple extends fruit{
    }
    public static List<? super fruit> list;
    public static void main(String[] args) throws Exception {
        Field field = test3.class.getDeclaredField("list");
        ParameterizedType parameterizedType = (ParameterizedType)field.getGenericType();
        Type type = parameterizedType.getActualTypeArguments()[0];
        System.out.println(type.getTypeName());
        if(type instanceof WildcardType){
            WildcardType wildcardType = (WildcardType)type;
            Type[] upperBounds = wildcardType.getUpperBounds();
            Type[] lowerBounds = wildcardType.getLowerBounds();
            if(upperBounds.length != 0){
                System.out.println(upperBounds[0].getTypeName());
            }else{
                System.out.println("UpperBounds is null.");
            }
            if(lowerBounds.length > 0){
                System.out.println(lowerBounds[0].getTypeName());
            }else{
                System.out.println("LowerBounds is null.");
            }
        }
    }
}
? super test3$fruit
java.lang.Object
test3$fruit