java反射--Type使用详解

Type简介

在API文档中,Type接口的说明如下:

Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。

API中提到的Type的组成部分说明如下:

原始类型:一般意义上的java类,由class类实现
参数化类型:ParameterizedType接口的实现类
数组类型:GenericArrayType接口的实现类
类型变量:TypeVariable接口的实现类
基本类型:int,float等java基本类型,其实也是class

Type使用场景

有很多场景下我们可以获得Type

  1. Class
  • getGenericInterfaces: 返回此类直接实现的所有接口的类型。接口的实现类通过该方法,可以获取所实现的接口的泛型类型,比如:接口Service,实现类UserServiceImpl,能够得到Service,
Type[] genericInterfaces = UserServiceImpl.class.getGenericInterfaces();
  • getGenericSuperclass: 返回此类所表示的实体的直接超类的类型。一个类的子类通过该方法,可以获取超类的泛型类型,比如:SuperClass,子类Main,能够得到SuperClass
// 获取 Main 的超类 SuperClass 的签名(携带泛型). 这里为: 
//SuperClass<User>
 Type genericSuperclass = Main.class.getGenericSuperclass();
  1. Method
    当我们拿到一个Method,用Method. getGenericParameterTypes()方法获得Type[],也就是方法的参数类型列表。
  2. Filed
    当我们拿到一个Class,用Class.getDeclaredFields()方法得到Field[],也就是类的属性列表,然后用Field. getGenericType()方法得到这个属性的Type类型。

Type的分类

Type接口包含了一个实现类(Class)和四个实现接口(TypeVariable, ParameterizedType, GenericArrayType, WildcardType),这四个接口都有自己的实现类,但这些实现类开发都不能直接使用,只能用接口。
在不同的场景下,java会使用上面五种实现类的其中一种,来解释要描述的类型。
这里先准备几段代码,以备说明:

  1. 代码–示例1
package xxx.xxx.xxx;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

abstract class SuperClass<T> {
}

class Main extends SuperClass<User> {

   public static void main(String[] args) {
       // 获取 Main 的超类 SuperClass 的签名(携带泛型). 这里为: xxx.xxx.xxx.SuperClass<xxx.xxx.xxx.User>
       Type genericSuperclass = Main.class.getGenericSuperclass();
       // 强转成 参数化类型 实体.
       ParameterizedType parameterizedType =
        (ParameterizedType) genericSuperclass;
       System.out.println(parameterizedType);

       // 获取超类的泛型类型数组. 即SuperClass<User>的<>中的内容,
       // 因为泛型可以有多个, 所以用数组表示
       Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
       Type genericType = actualTypeArguments[0];
       Class<User> clazz = (Class<User>) genericType;
       System.out.println(clazz);
   }

}

class User {
}


运行结果:
xxx.xxx.xxx.SuperClass<xxx.xxx.xxx.User>
class xxx.xxx.xxx.User
  1. 代码–示例2
public class TestReflect {

   public static void test(TestReflect p0,
   		List<TestReflect> p1,
   		Map<String,TestReflect> p2,
   		List<String>[] p3,
   		Map<String,TestReflect>[] p4,
   		List<? extends TestReflect> p5,
   		Map<? extends TestReflect,? super TestReflect> p6
   		//T p7
   		){
   	
   }

   public static void main(String[] args) {
   	
   	Method[] methods=TestReflect.class.getMethods();

   	for(int i=0;i<methods.length;i++){
   		Method oneMethod=methods[i];
   		
   		if(oneMethod.getName().equals("test")){
   			Type[] types=oneMethod.getGenericParameterTypes();
   			
   			//第一个参数,TestReflect p0
   			Class type0=(Class)types[0];
   			System.out.println("type0:"+type0.getName());
   			// 结果  :type0:com.byy.TestReflect
   			//第二个参数,List<TestReflect> p1
   			Type type1=types[1];
   			Type[] parameterizedType1=((ParameterizedType)type1)
   			.getActualTypeArguments();
   			Class parameterizedType1_0=(Class)parameterizedType1[0];
   			System.out.println("parameterizedType1_0:"
   			+parameterizedType1_0.getName());
   			// 结果  :parameterizedType1_0:com.byy.TestReflect
   			//第三个参数,Map<String,TestReflect> p2
   			Type type2=types[2];
   			Type[] parameterizedType2=((ParameterizedType)type2)
   			.getActualTypeArguments();
   			Class parameterizedType2_0=(Class)parameterizedType2[0];
   			System.out.println("parameterizedType2_0:"
   			+parameterizedType2_0.getName());
   			// 结果  :parameterizedType2_0:java.lang.String
   			Class parameterizedType2_1=(Class)parameterizedType2[1];
   			System.out.println("parameterizedType2_1:"
   			+parameterizedType2_1.getName());
   			// 结果  :parameterizedType2_1:com.byy.TestReflect
   			

   			//第四个参数,List<String>[] p3
   			Type type3=types[3];
   			Type genericArrayType3=((GenericArrayType)type3).getGenericComponentType();
   			ParameterizedType parameterizedType3=(ParameterizedType)genericArrayType3;
   			Type[] parameterizedType3Arr=parameterizedType3.getActualTypeArguments();
   			Class class3=(Class)parameterizedType3Arr[0];
   			System.out.println("class3:"+class3.getName());
   				// 结果  :class3:java.lang.String
   			//第五个参数,Map<String,TestReflect>[] p4
   			Type type4=types[4];
   			Type genericArrayType4=((GenericArrayType)type4).getGenericComponentType();
   			ParameterizedType parameterizedType4=(ParameterizedType)genericArrayType4;
   			Type[] parameterizedType4Arr=parameterizedType4.getActualTypeArguments();
   			Class class4_0=(Class)parameterizedType4Arr[0];
   			System.out.println("class4_0:"+class4_0.getName());
   			// 结果  :class4_0:java.lang.String
   			Class class4_1=(Class)parameterizedType4Arr[1];
   			System.out.println("class4_1:"+class4_1.getName());
   			// 结果  :class4_1:com.byy.TestReflect

   			//第六个参数,List<? extends TestReflect> p5
   			Type type5=types[5];
   			Type[] parameterizedType5=((ParameterizedType)type5).getActualTypeArguments();
   			Type[] parameterizedType5_0_upper=((WildcardType)parameterizedType5[0]).getUpperBounds();
   			Type[] parameterizedType5_0_lower=((WildcardType)parameterizedType5[0]).getLowerBounds();
   			
   			//第七个参数,Map<? extends TestReflect,? super TestReflect> p6
   			Type type6=types[6];
   			Type[] parameterizedType6=((ParameterizedType)type6).getActualTypeArguments();
   			Type[] parameterizedType6_0_upper=((WildcardType)parameterizedType6[0]).getUpperBounds();
   			Type[] parameterizedType6_0_lower=((WildcardType)parameterizedType6[0]).getLowerBounds();
   			Type[] parameterizedType6_1_upper=((WildcardType)parameterizedType6[1]).getUpperBounds();
   			Type[] parameterizedType6_1_lower=((WildcardType)parameterizedType6[1]).getLowerBounds();				
   		}
   	}
   }
}

Class

class可以描述的类型:

1.普通的java类(比如String,Integer,Method等等),
2.数组,
2.自定义类(比如我们自己定义的TestReflect,User类),
3.8种java基本类型(比如int,float等)

java会选择Class来作为这个Type的实现类,我们甚至可以直接把这个Type强行转换类型为Class。

对与class有两个关于类型的方法,getGenericInterfaces和getGenericSuperclass这个两个方法前面已经做过说明,这里就具体看看它的使用。

参考示例1的示例:Type genericSuperclass = Main.class.getGenericSuperclass();
获取的是Main类继承父类的class类型,结果为xxx.xxx.xxx.SuperClass<xxx.xxx.xxx.User>,若想获取继承父类泛型的类型,要通过 Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
进行获取,这里是返回的泛型类型的数组。可以通过
Type genericType = actualTypeArguments[0];
Class clazz = (Class) genericType;
System.out.println(clazz); 取出对象的泛型的class类型。
getGenericInterfaces 是返回的实现接口的类型,实现的接口可能是多个,这里是个数组。获取接口的类型和接口泛型的类型和上面类似。

ParameterizedType

当需要描述的类是泛型类时,比如List,Map等,不论代码里写没写具体的泛型,java会选择ParameterizedType接口做为Type的实现。

真正的实现类是sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl。

ParameterizedType接口有getActualTypeArguments()方法,用于得到泛型的Type类型数组。可以参考示例1的实现。

多个泛型参数的实现:

//第三个参数,Map<String,TestReflect> p2
Type type2=types[2];
Type[] parameterizedType2=((ParameterizedType)type2).getActualTypeArguments();
Class parameterizedType2_0=(Class)parameterizedType2[0];
System.out.println("parameterizedType2_0:"+parameterizedType2_0.getName());
Class parameterizedType2_1=(Class)parameterizedType2[1];
System.out.println("parameterizedType2_1:"+parameterizedType2_1.getName());

ype2是Map<String,TestReflect>,Map属于泛型类,同样java选择ParameterizedType作为type2的实现,type2可以直接转换类型为ParameterizedType。

使用getActualTypeArguments()得到的泛型类型数组parameterizedType2有两个元素,因为Map在泛型中可以写两个类型,本例中Map的泛型类型分别是String类和TestReflect,他们的Type都会被java用Class来实现,所以最后输出的是:

parameterizedType2_0:java.lang.String
parameterizedType2_1:com.webx.TestReflect

GenericArrayType

当需要描述的类型是泛型类的数组时,比如比如List[],Map[],type会用GenericArrayType接口作为Type的实现。

真正的实现类是sun.reflect.generics.reflectiveObjects. GenericArrayTypeImpl。

GenericArrayType接口有getGenericComponentType()方法,得到数组的组件类型的Type对象

示例2–>第四个参数的测试代码

//第四个参数,List<String>[] p3
Type type3=types[3];
Type genericArrayType3=((GenericArrayType)type3).getGenericComponentType();
ParameterizedType parameterizedType3=(ParameterizedType)genericArrayType3;
Type[] parameterizedType3Arr=parameterizedType3.getActualTypeArguments();
Class class3=(Class)parameterizedType3Arr[0];
System.out.println("class3:"+class3.getName());

type3是List[],所以java选择GenericArrayType作为type3的实现,type3可以直接转换类型为GenericArrayType。

调用getGenericComponentType()方法,得到数组的组件类型的Type对象,也就是本例中的变量genericArrayType3,他代表的是List类。

List是泛型类,所以变量genericArrayType3的Type用ParameterizedType来实现,转换类型之后也就是变量parameterizedType3。

parameterizedType3.getActualTypeArguments()得到的是List类型的泛型类数组,也就是数组parameterizedType3Arr。

数组parameterizedType3Arr只有一个元素,类型是String,这个Type由Class实现,就是变量class3,最后输出的是:

class3:java.lang.String

WildcardType

当需要描述的类型是泛型类,而且泛型类中的泛型被定义为(? extends xxx)或者(? super xxx)这种类型,比如List<? extends TestReflect>,这个类型首先将由ParameterizedType实现,当调用ParameterizedType的getActualTypeArguments()方法后得到的Type就由WildcardType实现。

真正的实现类是sun.reflect.generics.reflectiveObjects. WildcardTypeImpl。

WildcardType接口有getUpperBounds()方法,得到的是类型的上边界的Type数组,实际上就是类型的直接父类,也就是extends后面的类型。显然在当前java的设定中,这个数组只可能有一个元素,因为java现在只能extends一个类。如果实在没写extends,那他的直接父类就是Object。

WildcardType接口有getLowerBounds()方法,得到的是类型的下边界的Type数组,有super关键字时可能会用到,经测试不会得到类型的子类,而是只得到super关键字后面的类型,如果没写super关键字,则返回空数组。
示例2 第六个参数的测试代码:

//第六个参数,List<? extends TestReflect> p5
Type type5=types[5];
Type[] parameterizedType5=((ParameterizedType)type5).getActualTypeArguments();
Type[] parameterizedType5_0_upper=((WildcardType)parameterizedType5[0]).getUpperBounds();
Type[] parameterizedType5_0_lower=((WildcardType)parameterizedType5[0]).getLowerBounds();

ype5代表List<? extends TestReflect>,用ParameterizedType实现。

调用getActualTypeArguments()方法后,得到只有一个元素的Type数组,这个元素就代表(? extends TestReflect)

把这个Type元素转成WildcardType后,可以调用getUpperBounds()和getLowerBounds()方法得到上边界和下边界,在本例中的上边界就是变量parameterizedType5_0_upper,只有一个元素,该元素代表TestReflect类型,下边界是变量parameterizedType5_0_lower,是个空数组。

示例2 第七个参数的测试代码:

//第七个参数,Map<? extends TestReflect,? super TestReflect> p6
Type type6=types[6];
Type[] parameterizedType6=((ParameterizedType)type6).getActualTypeArguments();
Type[] parameterizedType6_0_upper=((WildcardType)parameterizedType6[0]).getUpperBounds();
Type[] parameterizedType6_0_lower=((WildcardType)parameterizedType6[0]).getLowerBounds();
Type[] parameterizedType6_1_upper=((WildcardType)parameterizedType6[1]).getUpperBounds();
Type[] parameterizedType6_1_lower=((WildcardType)parameterizedType6[1]).getLowerBounds();

type6代表Map<? extends TestReflect,? super TestReflect>,用ParameterizedType实现。

调用getActualTypeArguments()方法后,得到有两个元素的Type数组,两个元素分别代表(? extends TestReflect)和(? super TestReflect)

把这两个Type元素转成WildcardType后,可以调用getUpperBounds()和getLowerBounds()方法得到上边界和下边界。

在本例中第一个WildcardType的上边界就是变量parameterizedType6_0_upper,只有一个元素,该元素代表TestReflect类型,下边界是变量parameterizedType6_0_lower,是个空数组。

在本例中第二个WildcardType的上边界就是变量parameterizedType6_1_upper,只有一个元素,该元素代表Object类型,下边界是变量parameterizedType6_1_lower,只有一个元素,该元素代表TestReflect类型。

TypeVariable

Type的最后一种实现形式是TypeVariable接口,这种实现形式是在泛型类中使用的。

比如我们定义一个泛型类TestReflect,并在类中定义方法oneMethod(T para),那么当调用method.getGenericParameterTypes()方法得到的Type数组,数组的元素就是由TypeVariable接口实现的。

真正的实现类是sun.reflect.generics.reflectiveObjects. TypeVariableImpl。

参考扩展:Java 干货之深入理解Java泛型

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值