前言:
眼前各位老铁们对“反射与泛型java”大约比较关切,姐妹们都需要知道一些“反射与泛型java”的相关资讯。那么小编同时在网上收集了一些有关“反射与泛型java””的相关文章,希望看官们能喜欢,我们快快来学习一下吧!通常我们使用 Class 来描述数据类型,其实在 JDK 中有一个更通用的类型接口 Type,Type 是 JDK 中所有类型的公共父接口,Class 也是 Type 的其中一个实现类。
public interface Type { default String getTypeName() { return this.toString(); }}
在没有泛型之前,Java 只有原始类型(raw type),此时的类型都通过 Class 进行描述。
public final class Class<T> implements Serializable, GenericDeclaration, Type, AnnotatedElement
加入泛型之后,JDK 对类型进行了扩充,在 Class 之外添加了以下四种类型。
类型
描述
ParameterizedType
参数化类型,即常说的泛型,例如:List<String>、Map<Integer, String>
GenericArrayType
泛型数组类型,例如:T[]
TypeVariable
类型变量类型,例如:List<T> 中的 T
WildcardType
通配符类型,并不是 JAVA 类型,而是泛型表达式,例如:?、? super T、? extends T
ParameterizedType 的用法
ParameterizedType 表示参数化类型,所谓参数指的就是 <> 中的泛型。
public interface ParameterizedType extends Type { // 获取 <> 内的泛型类型 Type[] getActualTypeArguments(); // 获取原始类型,如果泛型结构为 O<T>,返回 O Type getRawType(); // 如果泛型结构为 O<T>.I<S>,返回外层的 O<T> Type getOwnerType(); }
获取父类的泛型信息
在 Class 类中有一个 getGenericSuperclass() 方法,用于获取带泛型信息的父类,如果父类不带泛型,则等同于 getSuperclass() 方法。
创建一个不带泛型的父类并实现
public class GenericService {}public class UserService extends GenericService {}
public class GenericTest { public static void main(String[] args) { Type genericSuperClass = UserService.class.getGenericSuperclass(); Class<? super UserService> superclass = UserService.class.getSuperclass(); System.out.println(genericSuperClass); System.out.println(superclass); System.out.println(genericSuperClass == superclass); }}
输出如下
class test.GenericServiceclass test.GenericServicetrue
可以看到 getGenericSuperclass 与 getSuperclass 返回的都是 Class,而且是同一个 Class。
接下来使用泛型,再次验证,这里需要两个类 UserRepository 与 User,自行创建即可。
public class GenericService<T, M> {}public class UserService extends GenericService<UserRepository, User> {}
再次运行,可以看到两者返回的对象已经不一样了,getGenericSuperclass 方法返回的是带了泛型信息的 ParameterizedType。
test.GenericService<test.UserRepository, test.User>class test.GenericServicefalse
通过 ParameterizedType 可以进一步获取到泛型
public class GenericTest { public static void main(String[] args) { Type genericSuperClass = UserService.class.getGenericSuperclass(); ParameterizedType parameterizedType = (ParameterizedType) genericSuperClass; // 获取原始类型 Class displayType(parameterizedType.getRawType()); // 获取泛型 Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (Type argument : actualTypeArguments) { displayType(argument); } } public static void displayType(Type type) { System.out.println(type.getTypeName() + " --- " + type.getClass().getSimpleName()); }}
输出结果
test.GenericService --- Classtest.UserRepository --- Classtest.User --- Class
获取接口的泛型信息
在 Class 类中还提供了一个 getGenericInterfaces() 方法,用于获取带泛型信息的接口。
创建两个接口,一个不带泛型,一个带泛型
public interface IA {}public interface IB<T, P extends Serializable> {}
创建一个实现类
public class Impl implements IA, IB<UserRepository, User> {}
获取接口的泛型
public class GenericTest { public static void main(String[] args) { Type[] genericInterfaces = Impl.class.getGenericInterfaces(); for (Type type : genericInterfaces) { if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; displayType(parameterizedType); Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); for (Type argument : actualTypeArguments) { displayType(argument); } } else { displayType(type); } System.out.println("-------------------------------"); } } public static void displayType(Type type) { System.out.println(type.getTypeName() + " --- " + type.getClass().getSimpleName()); }}
输出结果
test.IA --- Class-------------------------------test.IB<test.UserRepository, test.User> --- ParameterizedTypeImpltest.UserRepository --- Classtest.User --- Class-------------------------------
提供一个获取父类及接口泛型的工具类
public class ReflectUtils { /** * 获取父类指定位置的泛型类型 */ public static Class<?> getSuperClassGenericType(Class<?> clazz, int index) { Type genType = clazz.getGenericSuperclass(); if (!(genType instanceof ParameterizedType)) { log.warn(String.format("Warn: %s's superclass not ParameterizedType", clazz.getSimpleName())); return Object.class; } return indexOfGenericType(clazz, (ParameterizedType) genType, index); } /** * 获取指定接口指定位置的泛型类型 */ public static Class<?> getInterfaceGenericType(Class<?> clazz, Class<?> target, int index) { for (Type genericInterface : clazz.getGenericInterfaces()) { if (genericInterface instanceof ParameterizedType) { if (((ParameterizedType) genericInterface).getRawType() == target) { return indexOfGenericType(clazz, (ParameterizedType) genericInterface, index); } } else if (genericInterface == target) { log.warn(String.format("Warn: %s's interface not ParameterizedType", clazz.getSimpleName())); return Object.class; } } return Object.class; } public static Class<?> indexOfGenericType(Class<?> clazz, ParameterizedType type, int index) { Type[] params = type.getActualTypeArguments(); if (index >= params.length || index < 0) { log.warn(String.format("Warn: Index: %s, Size of %s's Parameterized Type: %s .", index, clazz.getSimpleName(), params.length)); return Object.class; } if (!(params[index] instanceof Class)) { log.warn(String.format("Warn: %s not set the actual class on superclass generic parameter", clazz.getSimpleName())); return Object.class; } return (Class<?>) params[index]; }}
获取字段的泛型类型
Field 类中提供了一个 getGenericType() 方法,用于获取带泛型信息的字段类型,如果不存在泛型信息,则该方法与 getType() 等效。
public class GenericTest { private List<String> list; private List unknownList; private Map<String, Long> map; private Map unknownMap; private Map.Entry<String, Long> entry; public static void main(String[] args) { Field[] fields = GenericTest.class.getDeclaredFields(); for (Field f : fields) { System.out.println(f.getName() + " is ParameterizedType: " + (f.getGenericType() instanceof ParameterizedType)); } }}
输出如下,可以看到,有没有泛型,不是看类声明有没有泛型,而是看变量声明时有没有带泛型。比如 unknownList 没有声明泛型,那么 getGenericType() 方法返回的就是 Class,而不是 ParameterizedType。
list is ParameterizedType: trueunknownList is ParameterizedType: falsemap is ParameterizedType: trueunknownMap is ParameterizedType: falseentry is ParameterizedType: true
获取泛型变量的泛型信息
public class GenericTest { private List<String> list; private List unknownList; private Map<String, Long> map; private Map unknownMap; private Map.Entry<String, Long> entry; public static void main(String[] args) { Field[] fields = GenericTest.class.getDeclaredFields(); for (Field f : fields) { if (f.getGenericType() instanceof ParameterizedType) { System.out.print(f.getName() + "<"); ParameterizedType genericType = (ParameterizedType) f.getGenericType(); Type[] typeArguments = genericType.getActualTypeArguments(); int i = 0; for (Type argument : typeArguments) { if (i++ > 0) { System.out.print(","); } System.out.print(argument.getTypeName()); } System.out.println(">"); } } }}
输出如下
list<java.lang.String>map<java.lang.String,java.lang.Long>entry<java.lang.String,java.lang.Long>
这里也可以看一下 getOwnerType() 方法的用法
public class GenericTest { private List<String> list; private List unknownList; private Map<String, Long> map; private Map unknownMap; private Map.Entry<String, Long> entry; public static void main(String[] args) { Field[] fields = GenericTest.class.getDeclaredFields(); for (Field f : fields) { if (f.getGenericType() instanceof ParameterizedType) { ParameterizedType genericType = (ParameterizedType) f.getGenericType(); System.out.println(f.getName() + " ownerType is " + (genericType.getOwnerType() == null ? "null" : genericType.getOwnerType().getTypeName())); } } }}
输出如下,可以看到,当泛型结构为 O<T>.I<S> 类型时,调用 getOwnerType() 会返回外层的 O<T>,否则返回空。
list ownerType is nullmap ownerType is nullentry ownerType is java.util.Map
获取方法的泛型信息
public class GenericTest { public static void main(String[] args) { Method[] methods = GenericTest.class.getDeclaredMethods(); for (Method method : methods) { if (method.getName().equals("test")) { Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { if (genericParameterType instanceof ParameterizedType) { System.out.println(genericParameterType.getTypeName()); } } } } } public <T> T test(List<String> l1, List<ArrayList<String>> l2, List<T> l3, List<? extends Number> l4, List<ArrayList<String>[]> l5, Map<Boolean, Integer> l6) { return null; }}
输出如下
java.util.List<java.lang.String>java.util.List<java.util.ArrayList<java.lang.String>>java.util.List<T>java.util.List<? extends java.lang.Number>java.util.List<java.util.ArrayList<java.lang.String>[]>java.util.Map<java.lang.Boolean, java.lang.Integer>GenericArrayType 的用法
GenericArrayType 表示泛型数组
public interface GenericArrayType extends Type { Type getGenericComponentType(); }
创建一个泛型类,包含一个泛型数组
public class Holder<T> { private T[] arrayData; public void test(List<String>[] listArray, T[] values) {}}
public class GenericTest { public static void main(String[] args) { Field[] fields = Holder.class.getDeclaredFields(); for (Field field : fields) { if (field.getGenericType() instanceof GenericArrayType) { GenericArrayType genericType = (GenericArrayType) field.getGenericType(); System.out.println(field.getName() + " is " + genericType.getTypeName() + " and componentType is " + genericType.getGenericComponentType().getTypeName()); } } }}
输出如下
arrayData is T[] and componentType is TTypeVariable 的用法
TypeVariable 表示泛型变量,只要泛型不是具体的类型,比如 <T>、<E extends T> 都归类为泛型变量。
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement { // 获取变量名 String getName(); // 获取原始类型 D getGenericDeclaration(); // 获取泛型的继承关系 Type[] getBounds(); AnnotatedType[] getAnnotatedBounds();}
获取方法的返回参数
public class GenericTest { public static void main(String[] args) { Method[] methods = GenericTest.class.getDeclaredMethods(); Method method = Arrays.stream(methods) .filter(v -> v.getName().equals("testTypeVariable")) .findAny().get(); Type type = method.getGenericReturnType(); displayType(type); TypeVariable typeVariable = (TypeVariable) type; System.out.println(typeVariable.getGenericDeclaration()); displayType(typeVariable.getBounds()[0]); } public static void displayType(Type type) { System.out.println(type.getTypeName() + " --- " + type.getClass().getSimpleName()); } public <T extends User> T testTypeVariable() { return null; }}
输出如下
T --- TypeVariableImplpublic test.User test.Test.testTypeVariable()test.User --- ClassWildcardType 的用法
WildcardType 表示通配符,即 <?> 这种,接口包含两个方法
getUpperBounds:通配符格式如 <? extends P> 这种,说明泛型类型继承自 P,getUpperBounds 方法可以获取到 P 的类型getLowerBounds:通配符格式如 <? super C> 这种,说明泛型类型是 C 的超类,getLowerBounds 方法可以获取到 C 的类型
public interface WildcardType extends Type { // 向上继承 Type[] getUpperBounds(); // 向下继承 Type[] getLowerBounds();}
获取方法的参数,获取参数中定义的通配符信息
public class GenericTest { public static void main(String[] args) { Method[] methods = GenericTest.class.getDeclaredMethods(); Method method = Arrays.stream(methods) .filter(v -> v.getName().equals("testWildcardType")) .findAny().get(); Type[] types = method.getGenericParameterTypes(); int index = 0; for (Type type : types) { ParameterizedType parameterizedType = (ParameterizedType) type; Type typeArgument = parameterizedType.getActualTypeArguments()[0]; System.out.println("参数" + ++index + "泛型类型:" + typeArgument.getClass().getSimpleName()); if (typeArgument instanceof WildcardType) { WildcardType wildcardType = (WildcardType) typeArgument; for (Type upperType : wildcardType.getUpperBounds()) { System.out.println(" upperType:" + upperType.getTypeName()); } for (Type lowerType : wildcardType.getLowerBounds()) { System.out.println(" lowerType:" + lowerType.getTypeName()); } } } } public <T> void testWildcardType(List<T> l1, List<?> l2, List<? extends T> l3, List<? super Integer> l4) { }}
输出如下
参数1泛型类型:TypeVariableImpl参数2泛型类型:WildcardTypeImpl upperType:java.lang.Object参数3泛型类型:WildcardTypeImpl upperType:T参数4泛型类型:WildcardTypeImpl upperType:java.lang.Object lowerType:java.lang.Integer
标签: #反射与泛型java