在看源码之前我们先来了解一下什么是Type
首先:Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型(Class)、参数化类型(Parameterized)、数组类型(GenericArrayType)、类型变量(TypeVariable)和基本类型(Class)。
首先我们先来看看其定义:
public interface Type {
default String getTypeName() { //返回一个字符串描述该类型
return toString();
}
}
我们再来看看其继承体系
根据类图我们可以看到Type拥有4个已知的子类:
GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。
ParameterizedType 表示参数化类型,如 Collection<String>
TypeVariable 是各种类型变量的公共高级接口。
WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。
以上为JDK API中的解释,看了似乎并没有搞明白其想说明什么
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
A.首先我们看一下ParameterizedType的接口定义
/**
* ParameterizedType表示参数化类型,也就是泛型,例如List<T>、Set<T>等;
*/
public interface ParameterizedType extends Type {
//获取泛型中的实际类型,可能会存在多个泛型,例如Map<K,V>,所以会返回Type[]数组;
Type[] getActualTypeArguments();
//获取声明泛型的类或者接口,也就是泛型中<>前面的那个值;
Type getRawType();
//通过getOwnerType()方法可以获取到内部类的“拥有者”;
//拥有者表示的含义--内部类的“父类”,例如: Map 就是 Map.Entry<K,V>的拥有者。
Type getOwnerType();
}
例子:
在下面的例子中ParamterizedType类拥有两个成员变量List<T> ,Set<String>我们获取到该类型之后会发现,他们都是ParamterizedTypeImpl类型,因为Set<String>和Set<Integer>实际上是一样的,都是泛型。
public class ParameterizedTypeTest<T> {
private List<T> list=null;
private Set<String> 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<T> {
private List<T> list=null;
private Set<Integer> set=null;
private Map<String,Integer> map=null;
private Map<Map<String,Integer>,Map<Object,Object>> map2=null;
/**
* 如果是ParameterizedTypeTest.class.getDeclaredField("map2");
* 那么结果如下:
* System.out.println(types[0]); //输出为:java.util.Map<java.lang.String, java.lang.Integer>
* System.out.println(types[1]); //输出为:java.util.Map<java.lang.Object, java.lang.Object>
*/
public static void testGetActualTypeArguments()throws NoSuchFieldException{
Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("map");
Type typeMap=fieldMap.getGenericType();
ParameterizedType parameterizedTypeMap=(ParameterizedType)typeMap;
Type[] types=parameterizedTypeMap.getActualTypeArguments();
System.out.println(types[0]); //输出为:class java.lang.String
System.out.println(types[1]); //输出为:class java.lang.Integer
}
public static void main(String[] args) throws NoSuchFieldException{
testGetActualTypeArguments();
}
}
再来看看getRawType方法:获取声明泛型的类或者接口,说明了也就是这个泛型是被谁声明的,例子如下:
public class ParameterizedTypeTest<T> {
private List<T> list=null;
private Set<Integer> set=null;
private Map<String,Integer> 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
}
}
最后再来getOwnerType()方法
public class ParameterizedTypeTest<T> {
private Map.Entry<String,Integer> 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<String>[] 、T[]等
*/
public interface GenericArrayType extends Type {
/**
* 返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)、
* T[] 中的T(TypeVariableImpl)
*/
Type getGenericComponentType();
}
例子:
public class GenericArrayTypeTest<T> {
private T[] t;
private List<String>[] 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
}
}
通过上述例子可以看出:GenericArrayType表示的是泛型数组类型
再来看看其接口方法:getGenericComponentType
public class GenericArrayTypeTest<T> {
private T[] t;
private List<String>[] 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<java.lang.String>
TestGetGenericComponentType("t"); //输出 T
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再来看看TypeVariable
/**
* 泛型的类型变量,指的是List<T>、Map<K,V>中的T,K,V等值,
* 实际的Java类型是TypeVariableImpl(TypeVariable的子类);
* 此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限;
*/
interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
/**
* 获得该类型变量的上限,也就是泛型中extend右边的值;
* 例如 List<T extends Number> ,Number就是类型变量T的上限;
* 如果我们只是简单的声明了List<T>(无显式定义extends),那么默认为Object;
* 值得注意的是,类型变量的上限可以为多个,必须使用&符号相连接,
* 例如 List<T extends Number & Serializable>;其中,& 后必须为接口;
*/
Type[] getBounds();
//获取声明该类型变量实体
D getGenericDeclaration();
//获取类型变量在源码中定义的名称;
String getName();
//这个方法是JDK1.8中的新方法,目前还不清楚其作用
AnnotatedType[] getAnnotatedBounds();
}
先来看看用法:
public class TypeVariableTest<T> {
private List<T> 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<T extends Number & Serializable & Comparable> {
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<T> {
private List<T> 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
}
}
}
再来看看getGenericDeclaration方法
public class TypeVariableTest<T> {
private T t;
@Test //获取声明该类型变量实体,也就是TypeVariableTest<T>中的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
}
}
里面涉及到了一个类 GenericDeclaration 顺便看看该类
含义为:声明类型变量的所有实体的公共接口;也就是说该接口定义了哪些地方可以定义类型变量(泛型);该类的继承结构如下:
也就是说,只有在以上三种子类中才可以定义泛型
public class TestGenericDeclarationForClass<T> {
//测试在Class定义泛型
}
class TestGenericDeclarationForConstruct{
public <T> TestGenericDeclarationForConstruct(T t){
//测试在构造方法定义泛型
}
}
class TestGenericDeclarationForMethod{
public <T> void test(T t){
//测试在方法定义泛型
}
}
再来看看方法getName 这个方法就比较好理解了
public class TypeVariableTest<T> {
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
}
}
当我们没有声明泛型的时候,我们普通的对象就是一个Class类型,是Type中的一种;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最后再来看看 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
}
}
在来看看方法getUpperBounds()
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
}
}
最后再来看看方法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();
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
}
}