Java反射中的泛型

java.lang.reflect中的泛型结构体系

从jdk1.5开始,Java引入了泛型的特性,同时也在reflect包下提供了对反射泛型的支持。

废话不多说,通过一个uml类图,了解一下相关的类和接口,下面再详细说明。


Type


这个接口非常重要,jdk关于Type接口的介绍:

Type是Java语言中所有类型的共同父接口。这些类型包括原生类型,参数化类型,数组类型,类型变量以及基本数据类型。Class实现了这个接口。

raw types : Java类和接口

parameterized types : 参数化类型,如List<String>就是一个参数化类型

type variables : 类型参数,如java.util.List<E>中的E,即为类型变量

primitive types : 基本数据类型,包括 int、double、float、short、byte、long、char、boolean

GenericDeclaration


jdk解释的很清楚了,所有声明了类型变量的实体都应该实现这个接口。

实现了这个接口的有Class和Method,所以Java中有泛型类和泛型方法。

TypeVariable

在Type中,已经解释了TypeVariable的含义,他就是声明泛型声明中的参数变量,如java.util.List<E>中的E : 


看一下TypeVariable类型的声明:


这里要注意到,TypeVariable自身也声明了泛型参数D,代表泛型参数所属的实体对象,GenericDeclaration代表的可能是一个Class或Method。

ParameterizedType

参数化类型,如我们在代码中声明了一个数据域:


List<String>就是一个参数化类型。

ParameterizedType中定义了获取泛型参数实际类型的方法:


WildcardType

通配符类型,如:


?extend Number 就是WildcardType,当然,它也是TypeVariable类型的

GenericArrayType

故名思义,它代表的是泛型数组类型,如:


GenericArrayType中定义了获取数组元素类型的方法:


示例代码

下面的类型仅仅为了展示反射泛型API的用法,没有任何业务上的含义:

package org.lin.rg;

import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

//泛型类
public class GenericType <L extends List<String>,
				T extends SuperClass & Interface1 & Interface2>{ //仅仅是标记类型和接口,内不含方法
	
	//泛型数组
	@SuppressWarnings({ "unused", "unchecked" })
	private Class<? extends Number>[] numberTypes = new Class[10];
	
	@SuppressWarnings({ "unused" })
	private List<String> list = new ArrayList<>();
	
	@SuppressWarnings("unused")
	private List<? extends Number> numberList = new ArrayList<>();
	
	//带泛型类参数的方法
	public List<String> getList(Map<String, Object> map, List<Integer> list) {
		return null;
	}
	
	static class Foo extends SuperClass implements Interface1, Interface2 {}
	
	@SuppressWarnings("rawtypes")
	public static void showTypeVariables() {
		Class<GenericType> clazz = GenericType.class;
		//这个方法在GenericDeclaration中定义,用于获取类型变量
		TypeVariable<?>[] typeParameters = clazz.getTypeParameters();
		System.out.println("打印" + clazz.getSimpleName() + "定义的参数类型:");
		for (TypeVariable<?> param : typeParameters) {
			System.out.println("参数名:" + param.getName());
			System.out.println("参数上界列表:" + Arrays.asList(param.getBounds()));
		}
		System.out.println();
	}
	
	public static void showParameterType() {
		//这里,我用list数据域展示ParameterizedType API
		try {
			Field field = GenericType.class.getDeclaredField("list");
			//注意,一定要使用带Generic前缀的方法
			Type fieldType = field.getGenericType();
			System.out.println("ParameterizedType: " + fieldType);
			if (fieldType instanceof ParameterizedType) {
				ParameterizedType pt = (ParameterizedType)fieldType;
				Type actualType = pt.getActualTypeArguments()[0];
				System.out.println(actualType);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println();
	}
	
	public static void showWildcardType() {
		try {
			Field field = GenericType.class.getDeclaredField("numberList");
			ParameterizedType fieldType = (ParameterizedType)field.getGenericType();
			WildcardType wt = (WildcardType)fieldType.getActualTypeArguments()[0];
			System.out.println("WildcardType upperBounds:" + Arrays.asList(wt.getUpperBounds()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println();
	}
	
	public static void showGenericArrayType() {
		try {
			Field field = GenericType.class.getDeclaredField("numberTypes");
			GenericArrayType gat = (GenericArrayType)field.getGenericType();
			System.out.println("array component type :" + gat.getGenericComponentType());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		showTypeVariables();
		showParameterType();
		showWildcardType();
		showGenericArrayType();
	}
}
	

输出:



阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页