简介
说明
Type 是java反射机制中提供的一个接口,用来表示java中的所有类型的接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。(这段话是Type源码的注释中写的)。
- 原始类型:一般意义上的java类,由class类实现
- 参数化类型:ParameterizedType接口的实现类
- 数组类型:GenericArrayType接口的实现类
- 类型变量:TypeVariable接口的实现类
- 基本类型:int,float等java基本类型。(其实也是class)
Type类几乎在各种框架中都能看到,尤其是涉及代理,反射的地方。理解好Type类也会对今后框架封装、源码解读有很大好处。
Type接口源码
package java.lang.reflect; /** * Type is the common superinterface for all types in the Java * programming language. These include raw types, parameterized types, * array types, type variables and primitive types. * * @since 1.5 */ public interface Type { /** * Returns a string describing this type, including information * about any type parameters. * * @implSpec The default implementation calls {@code toString}. * * @return a string describing this type * @since 1.8 */ default String getTypeName() { return toString(); } }
Type的子接口/子类
Type的子接口/子类是这样的:
实例
下边我只用字段进行示例。方法、类都是一样的用法。
Class
Class的方法实在太多了,毕竟它包含了类的所有信息。详细可见这里:Java反射-反射的应用 – 自学精灵
本处只做一个简单的示例。
package com.example.a; import java.lang.reflect.Field; import java.lang.reflect.Method; class ClassTest{ private String userName; public void sayHello() { System.out.println("Hello"); } } public class Demo { public static void main(String[] args) { Field[] declaredFields = ClassTest.class.getDeclaredFields(); Method[] declaredMethods = ClassTest.class.getDeclaredMethods(); for (Field declaredField : declaredFields) { System.out.println(declaredField.getName()); } for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod.getName()); } } }
ParameterizedType
参数化类型,即带泛型的类型;例如:List<T>、Map<K,V>。
源码
public interface ParameterizedType extends Type { //获取参数化类型参数。例如:Map<K,V>,则为K/V数组; Type[] getActualTypeArguments(); //获取原始类型,泛型类型。例如:List<T> ,则为 List Type getRawType(); //如果是内部类,获取拥有内部类的外部类。例如:Map.Entry<K,V>,则为Map Type getOwnerType(); }
实例
package com.example.a; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; class ParameterizedTypeTest<T> { private List<T> tList; private Map<String, Integer> stringIntegerMap; } public class Demo { public static void main(String[] args) { Field[] declaredFields = ParameterizedTypeTest.class.getDeclaredFields(); for (Field declaredField : declaredFields) { // 获得字段的类型 Type type = declaredField.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; // 参数类型名。输出:List<T> 和 Map<String,Integer> System.out.println("typeName: " + parameterizedType.getTypeName()); // 父类。本处都是Null System.out.println("ownerType: " + parameterizedType.getOwnerType()); // 原始类型。输出:interface java.util.List/Map System.out.println("rawType: " + parameterizedType.getRawType()); // 参数实际类型。输出:T和java.lang.String/Integer for (Type arguments : parameterizedType.getActualTypeArguments()) { System.out.println(arguments.getTypeName()); } } System.out.println("----------------------------------"); } } }
运行结果
typeName: java.util.List<T> ownerType: null rawType: interface java.util.List T ---------------------------------- typeName: java.util.Map<java.lang.String, java.lang.Integer> ownerType: null rawType: interface java.util.Map java.lang.String java.lang.Integer ----------------------------------
TypeVariable
类型变量,即泛型中的变量;例如:T、K、V等变量,可以表示任何类;
TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型。
源码
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement { //获得该类型变量的上限,也就是泛型中extend右边的值; // 例如: List<T extends Number> ,Number就是类型变量T的上限; Type[] getBounds(); //获取声明该类型变量实体 D getGenericDeclaration(); String getName(); AnnotatedType[] getAnnotatedBounds(); }
实例
package com.example.a; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.List; import java.util.Map; class TypeVariableTest<T> { private List<Integer> integerList; private Map<String, T> stringTMap; } public class Demo { public static void main(String[] args) { Class<TypeVariableTest> clazz = TypeVariableTest.class; Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { Type type = declaredField.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type; for (Type type1 : parameterizedType.getActualTypeArguments()) { if (type1 instanceof TypeVariable) { TypeVariable typeVariable = (TypeVariable) type1; System.out.println("字段名: " + declaredField.getName()); System.out.println("typeName: " + typeVariable.getTypeName()); System.out.println("genericDeclaration: " + typeVariable.getGenericDeclaration()); } } } } } }
执行结果
字段名: stringTMap typeName: T genericDeclaration: class com.example.a.TypeVariableTest
可以发现,经过代码的过滤后,只获取到了T。
GenericArrayType
简介
泛型数组类型,用来描述ParameterizedType、TypeVariable类型的数组;例如:List<T>[] 、T[]、List<Integer>[]等。不包含String[]、int[]这种。
源码
public interface GenericArrayType extends Type { //可以获取到数组前面的类型。例如:List<String>[]为List<String> Type getGenericComponentType(); }
实例
package com.example.a; import java.lang.reflect.*; import java.util.List; class TypeVariableTest<T> { private T[] ts; private Integer[] integers; private List<Integer>[] integerList; private List<T>[] tLists; } public class Demo { public static void main(String[] args) { Class<TypeVariableTest> clazz = TypeVariableTest.class; Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { Type type = declaredField.getGenericType(); if (type instanceof GenericArrayType) { GenericArrayType genericArrayType = (GenericArrayType)type; System.out.println("字段名: " + declaredField.getName()); System.out.println("typeName: " + genericArrayType.getTypeName()); System.out.println("genericComponentType: " + genericArrayType.getGenericComponentType()); } System.out.println("------------------------------------------"); } } }
执行结果
字段名: ts typeName: T[] genericComponentType: T ------------------------------------------ ------------------------------------------ 字段名: integerList typeName: java.util.List<java.lang.Integer>[] genericComponentType: java.util.List<java.lang.Integer> ------------------------------------------ 字段名: tLists typeName: java.util.List<T>[] genericComponentType: java.util.List<T> ------------------------------------------
可见:Integer[]这种不属于GenericArrayType
WildType
简介
泛型表达式(通配符表达式)。例如:? extend Number、? super Integer。
WildcardType虽然是Type的子接口,但却不是Java类型中的一种。
源码
public interface WildcardType extends Type { // 获取上边界。例如:List<? extends Number>,则为Number Type[] getUpperBounds(); // 获取下边界。例如:List<? super String>, 则为String Type[] getLowerBounds(); }
实例
package com.example.a; import java.lang.reflect.*; import java.util.Arrays; import java.util.List; class TypeVariableTest { private List<? extends Integer> integerList; } public class Demo { public static void main(String[] args) { Class<TypeVariableTest> clazz = TypeVariableTest.class; Field[] declaredFields = clazz.getDeclaredFields(); for (Field declaredField : declaredFields) { Type type = declaredField.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; Type[] typeArguments = parameterizedType.getActualTypeArguments(); System.out.println("字段名: " + declaredField.getName()); for (Type type1 : typeArguments) { if (type1 instanceof WildcardType) { WildcardType wildcardType = (WildcardType) type1; System.out.println("typeName: " + wildcardType.getTypeName()); System.out.println("upperBounds: " + Arrays.toString(wildcardType.getUpperBounds())); } } } } } }
执行结果
字段名: integerList typeName: ? extends java.lang.Integer upperBounds: [class java.lang.Integer]
框架对Type的应用
Mybatis
org.apache.ibatis.reflection.Reflector中的typeClass方法将Type类型对象转换为Class对象。
private Class<?> typeToClass(Type src) { Class<?> result = null; // 如果src是Class类型的实例则直接进行强制类型转换 if (src instanceof Class) { result = (Class<?>) src; // 如果src是参数类型则获取其原始类型Class对象; } else if (src instanceof ParameterizedType) { result = (Class<?>) ((ParameterizedType) src).getRawType(); // 如果src是数组泛型类型,则分情况处理 } else if (src instanceof GenericArrayType) { Type componentType = ((GenericArrayType) src).getGenericComponentType(); if (componentType instanceof Class) { result = Array.newInstance((Class<?>) componentType, 0).getClass(); } else { Class<?> componentClass = typeToClass(componentType); result = Array.newInstance(componentClass, 0).getClass(); } } if (result == null) { result = Object.class; } return result; }
请先
!