在看源码之前我们先来了解一下什么是Type
首先:Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型(Class)、参数化类型(Parameterized)、数组类型(GenericArrayType)、类型变量(TypeVariable)和基本类型(Class)。
首先我们先来看看其定义:
public interface Type {
default String getTypeName() { //返回一个字符串描述该类型
return toString();
}
}
我们再来看看其继承体系
根据类图我们可以看到Type拥有4个已知的子类:
GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。
ParameterizedType 表示参数化类型,如 Collection
TypeVariable 是各种类型变量的公共高级接口。
WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。
以上为JDK API中的解释,看了似乎并没有搞明白其想说明什么
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
A.首先我们看一下ParameterizedType的接口定义
/**
* ParameterizedType表示参数化类型,也就是泛型,例如List、Set等;
*/
public interface ParameterizedType extends Type {
//获取泛型中的实际类型,可能会存在多个泛型,例如Map,所以会返回Type[]数组;
Type[] getActualTypeArguments();
//获取声明泛型的类或者接口,也就是泛型中<>前面的那个值;
Type getRawType();
//通过getOwnerType()方法可以获取到内部类的“拥有者”;
//拥有者表示的含义--内部类的“父类”,例如: Map 就是 Map.Entry的拥有者。
Type getOwnerType();
}
例子:
在下面的例子中ParamterizedType类拥有两个成员变量List
public class ParameterizedTypeTest {
private List list=null;
private Set set=null;
public static void main(String[] args) throws NoSuchFieldException{
Field fieldList=ParameterizedTypeTest.class.getDeclaredField("list");
//获取该属性的泛型类型
Type typeList=fieldList.getGenericType();
//获取实际的Type类型
System.out.println(typeList.getClass().getName()); //输出为: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
Field fieldSet=ParameterizedTypeTest.class.getDeclaredField("set");
//获取该属性的泛型类型
Type typeSet=fieldList.getGenericType();
//获取实际的Type类型
System.out.println(typeSet.getClass().getName()); //输出为: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
}
}
我们再来看看其接口方法
首先是getActualTypeArguments : 根据名称,其实也可以猜出其作用:就是获取泛型参数的实际类型。有一点需要注意的是,Java的泛型采用的是擦除发实现了,那么在运行时又能动态的获取泛型的实际类型,就足以证明,泛型类型还是通过某种方式写入到了class文件中
例子如下:
public class ParameterizedTypeTest {
private List list=null;
private Set set=null;
private Map map=null;
private Map
再来看看getRawType方法:获取声明泛型的类或者接口,说明了也就是这个泛型是被谁声明的,例子如下:
public class ParameterizedTypeTest {
private List list=null;
private Set set=null;
private Map map=null;
@Test
public void testGetRawType() throws NoSuchFieldException{
Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("map");
//getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型
Type typeMap=fieldMap.getGenericType();
ParameterizedType parameterizedTypeMap= (ParameterizedType) typeMap;
Type type=parameterizedTypeMap.getRawType();
System.out.println(type.getTypeName()); //输出 java.util.Map
}
}
public class ParameterizedTypeTest {
private Map.Entry mapEntry;
@Test
public void testGetRawType() throws NoSuchFieldException{
Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("mapEntry");
//getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型
Type typeMap=fieldMap.getGenericType();
ParameterizedType parameterizedTypeMap= (ParameterizedType) typeMap;
Type type=parameterizedTypeMap.getRawType();
System.out.println(type.getTypeName()); //输出 java.util.Map$Entry
System.out.println(parameterizedTypeMap.getOwnerType()); //输出 interface java.util.Map
}
}
再来看看GenericArrayType
首先先看看定义
/**
* 泛型数组类型,例如List[] 、T[]等
*/
public interface GenericArrayType extends Type {
/**
* 返回泛型数组中元素的Type类型,即List[] 中的 List(ParameterizedTypeImpl)、
* T[] 中的T(TypeVariableImpl)
*/
Type getGenericComponentType();
}
例子:
public class GenericArrayTypeTest {
private T[] t;
private List[] listArray;
@Test
public void TestGetGenericComponentType()throws NoSuchFieldException{
Field fieldListArray=GenericArrayTypeTest.class.getDeclaredField("listArray");
Type typeListArray=fieldListArray.getGenericType();
System.out.println(typeListArray.getClass().getName()); //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
Field fieldT =GenericArrayTypeTest.class.getDeclaredField("t");
Type typeT=fieldT.getGenericType();
System.out.println(typeT.getClass().getName()); //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl
}
}
再来看看其接口方法:getGenericComponentType
public class GenericArrayTypeTest {
private T[] t;
private List[] listArray;
public void TestGetGenericComponentType(String filedName)throws NoSuchFieldException{
Field fieldListArray=GenericArrayTypeTest.class.getDeclaredField(filedName);
Type typeListArray=fieldListArray.getGenericType();
GenericArrayType genericArrayType=(GenericArrayType)typeListArray;
Type type=genericArrayType.getGenericComponentType();
System.out.println(type.getTypeName());
}
@Test
public void print()throws NoSuchFieldException{
TestGetGenericComponentType("listArray"); //输出 java.util.List
TestGetGenericComponentType("t"); //输出 T
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再来看看TypeVariable
/**
* 泛型的类型变量,指的是List、Map中的T,K,V等值,
* 实际的Java类型是TypeVariableImpl(TypeVariable的子类);
* 此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限;
*/
interface TypeVariable extends Type, AnnotatedElement {
/**
* 获得该类型变量的上限,也就是泛型中extend右边的值;
* 例如 List ,Number就是类型变量T的上限;
* 如果我们只是简单的声明了List(无显式定义extends),那么默认为Object;
* 值得注意的是,类型变量的上限可以为多个,必须使用&符号相连接,
* 例如 List;其中,& 后必须为接口;
*/
Type[] getBounds();
//获取声明该类型变量实体
D getGenericDeclaration();
//获取类型变量在源码中定义的名称;
String getName();
//这个方法是JDK1.8中的新方法,目前还不清楚其作用
AnnotatedType[] getAnnotatedBounds();
}
先来看看用法:
public class TypeVariableTest {
private List list;
@Test
public void testTypeVariable()throws NoSuchFieldException{
Field fieldList=TypeVariableTest.class.getDeclaredField("list");
Type typeList=fieldList.getGenericType();
ParameterizedType parameterizedTypeList=(ParameterizedType)typeList;
Type[] types=parameterizedTypeList.getActualTypeArguments();
System.out.println(types[0].getClass().getName()); //输出 sun.reflect.generics.reflectiveObjects.TypeVariableImpl
}
}
再来看看getBounds()方法
public class TypeVariableTest {
private T t;
@Test
public void testGetBounds()throws NoSuchFieldException{
Field fieldT=TypeVariableTest.class.getDeclaredField("t");
TypeVariable typeVariable= (TypeVariable) fieldT.getGenericType();
Type[] types=typeVariable.getBounds();
for(Type type : types){
System.out.print(type + " "); //输出 class java.lang.Number interface java.io.Serializable interface java.lang.Comparable
}
}
}
public class TypeVariableTest {
private List list;
@Test
public void testTypeVariable()throws NoSuchFieldException{
Field fieldList=TypeVariableTest.class.getDeclaredField("list");
Type typeList=fieldList.getGenericType();
ParameterizedType parameterizedTypeList=(ParameterizedType)typeList;
Type[] types=parameterizedTypeList.getActualTypeArguments();
TypeVariable typeVariable=(TypeVariable)types[0];
Type[] types2=typeVariable.getBounds();
for(Type type : types2){
System.out.print(type + " "); //输出 class java.lang.Object
}
}
}
public class TypeVariableTest {
private T t;
@Test //获取声明该类型变量实体,也就是TypeVariableTest中的TypeVariableTest;
public void testGetGenericDeclaration()throws NoSuchFieldException{
Field fieldT=TypeVariableTest.class.getDeclaredField("t");
TypeVariable typeVariable=(TypeVariable)fieldT.getGenericType();
GenericDeclaration genericDeclaration=typeVariable.getGenericDeclaration();
System.out.println(genericDeclaration); //输出 class TypeVariableTest
}
}
含义为:声明类型变量的所有实体的公共接口;也就是说该接口定义了哪些地方可以定义类型变量(泛型);该类的继承结构如下:
也就是说,只有在以上三种子类中才可以定义泛型
public class TestGenericDeclarationForClass {
//测试在Class定义泛型
}
class TestGenericDeclarationForConstruct{
public TestGenericDeclarationForConstruct(T t){
//测试在构造方法定义泛型
}
}
class TestGenericDeclarationForMethod{
public void test(T t){
//测试在方法定义泛型
}
}
再来看看方法getName 这个方法就比较好理解了
public class TypeVariableTest {
private T t;
@Test
public void testGetName()throws NoSuchFieldException{
Field fieldT=TypeVariableTest.class.getDeclaredField("t");
TypeVariable typeVariable=(TypeVariable)fieldT.getGenericType();
System.out.println(typeVariable.getName()); //输出 T
}
}
再来看看Class类 (Class 类就不是接口,而是实现类了)
Type接口的实现类,是我们工作中常用到的一个对象;在Java中,每个.class文件在程序运行期间,都对应着一个Class对象,这个对象保存有这个类的全部信息;因此,Class对象也称之为Java反射的基础;
public class ClassTest {
private ClassTest classTest;
@Test
public void testClass()throws NoSuchFieldException{
Field field=ClassTest.class.getDeclaredField("classTest");
Type type=field.getGenericType();
System.out.println(type); //class ClassTest
}
}
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最后再来看看 WildcardType
定义如下:
/**
* 通配符表达式,表示通配符泛型
* 例如:List extends Number> 和 List super Integer>;
*/
public interface WildcardType extends Type {
//获取泛型变量的上边界(extends)
Type[] getUpperBounds();
//获取泛型变量的下边界(super)
Type[] getLowerBounds();
}
获取该对象例子:
public class WildcardTypeTest {
private List extends Number> listNum;
private List super String> listStr;
public void testWildcardType(String fieldName)throws NoSuchFieldException{
Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName);
ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType();
Type[] types=parameterizedTypeNum.getActualTypeArguments();
System.out.println(types[0].getClass());
}
@Test
public void print()throws NoSuchFieldException{
testWildcardType("listNum"); //输出 class sun.reflect.generics.reflectiveObjects.WildcardTypeImpl
testWildcardType("listStr"); //输出 class sun.reflect.generics.reflectiveObjects.WildcardTypeImpl
}
}
public class WildcardTypeTest {
private List extends Number> listNum;
private List super String> listStr;
public void testWildcardType(String fieldName)throws NoSuchFieldException{
Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName);
ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType();
Type[] types=parameterizedTypeNum.getActualTypeArguments();
WildcardType wildcardType=(WildcardType)types[0];
System.out.println(wildcardType.getUpperBounds()[0]);
//System.out.println(wildcardType.getLowerBounds()[0]);
}
@Test
public void print()throws NoSuchFieldException{
testWildcardType("listNum"); //输出 class java.lang.Number
}
}
public class WildcardTypeTest {
private List extends Number> listNum;
private List super String> listStr;
public void testWildcardType(String fieldName)throws NoSuchFieldException{
Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName);
ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType();
Type[] types=parameterizedTypeNum.getActualTypeArguments();
WildcardType wildcardType=(WildcardType)types[0];
//System.out.println(wildcardType.getUpperBounds()[0]);
System.out.println(wildcardType.getLowerBounds()[0]);
}
@Test
public void print()throws NoSuchFieldException{
testWildcardType("listStr"); //输出 class java.lang.String
}
}