Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。
通过反射机制,程序员可以更深入地控制程序的运行过程
Class类
所有类均继承Object类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。
Class text=demo.getClass(); //demo为某一类的对象
Class text=demo.class;
利用Class类的对象,可以访问返回某一对象的描述信息
组成部分 | 访问方法 | 返回值类型 | 说明 |
---|---|---|---|
包路径 | getPackage() | Package对象 | 获得该类的存放路径 |
类名称 | getName() | String 对象 | 获得该类的名称 |
继承类 | getSuperClass() | Class对象 | 获得该类的继承类 |
实现接口 | getInterfaces() | Class型数组 | 获得该类实现的所有接口 |
构造方法 | getConstructors() | Constructor数组 | 获得所有权限为public的构造方法 |
构造方法 | getConstructors(Class<?> …parameterTypes) | Constructor对象 | 获得权限为public的指定构造方法 |
构造方法 | getDeclaredConstructors() | Constructor数组 | 获得所有构造方法,按声明顺序返回 |
构造方法 | getDeclaredConstructors(Class<?> …parameterTypes | Constructor对象 | 获得指定构造方法 |
方法 | getMethods() | Method型数组 | 获得所有权限为public的方法 |
方法 | getMethod(String name,Class<?> …parameterTypes | Method对象 | 获得权限为public的指定方法 |
方法 | getDeclaredMethods() | Method型数组 | 获得所有方法,按声明顺序返回 |
方法 | getDeclaredMethod(String name,Class<?> …parameterTypes | Method对象 | 获得指定方法 |
成员变量 | getFields() | Field型数组 | 获得所有权限为public的成员变量 |
成员变量 | getFields(String name) | Field对象 | 获得权限为public的指定成员变量 |
成员变量 | getDeclaredFields() | Field型数组 | 获得所有成员变量,按声明顺序返回 |
成员变量 | getDeclaredFields() | Field对象 | 获得指定成员变量 |
内部类 | getClasses() | Class型数组 | 获得所有权限为public的内部类 |
内部类 | getDeclaredClasses() | Class对象 | |
内部类的声明类 | getDeclaringClass() | Class对象 | 如果该类为内部类,则返回它的成员类,否则返回null |
getFields()和getMethods()方法依次获得权限为public的成员变量和方法时,将包含从超类中继承到的成员变量和方法。getDeclaredFields()和getDeclaredMethods()方法只是获得在本类中定义的所有成员变量和方法
Class类与反射
通过反射机制,可以在程序中访问已经装载到JVM中的对象的描述,实现访问,检测和修改描述对象本身信息。在java.lang.reflect包中提供了对该功能的支持。
通过Class的相应方法和java.lang,reflect下的类就可以反射出相应的信息
Modifier类 (访问修饰符)
java.lang,reflect.Modifier
可以解析出getModifiers()方法(Class类,Construcor类,Filed类,Method类的方法)的返回值所表示的修饰符信息,因为getModifiers()方法返回的是int类型,无法直接得出修饰符信息,所以就需要Modeifier类来解析int值。可以通过toString(getModifiers())获得修饰符
Modifier.toSting(getModifiers())
Modifier的常用方法
方法 | 返回值 | 说明 |
---|---|---|
isStatic(int mod) | static boolean | 如果整数参数包含 public修饰符,则返回 true , false |
isProtected(int mod) | static boolean | 如果整数参数包含 protected修饰符,则返回 true |
isPrivate(int mod) | static boolean | 如果整数参数包含 private修饰符,则返回 true |
isFinal(int mod) | static boolean | 如果整数参数包含 final修饰符,则返回 true |
isStatic(int mod) | static boolean | 如果整数参数包含 static修饰符,则返回 true |
toString(int mod) | static String | 返回描述指定修饰符中的访问修饰符标志的字符串。 |
int modifiter=constructer.getModifiers();
String d=Modifiter.toString(modifiter); //静态方法,类名.方法名调用
boolean isPrivate=Modifier.isPrivate(modifiter)
Construcor类 (访问构造方法)
Construcor:构造方法类
java.lang,reflect.Construcor
getConstructors():返回Constructor数组 获得所有权限为public的构造方法
getConstructors(Class<?> …parameterTypes):返回Constructor对象 获得权限为public的指定构造方法
getDeclaredConstructors():返回Constructor数组 获得所有构造方法,按声明顺序返回
getDeclaredConstructors(Class<?> …parameterTypes):返回Constructor对象 获得指定构造方法
如果是访问指定的构造方法,需要根据该构造方法的入口参数类型来访问。有以下两种方法
objectclass.getDeclaredConstructors(String.class,int.class);
objectclass.getDeclaredConstructors(new Class[]{String.class,int.class});
Constructor类中的常用方法
方法 | 返回值 | 说明 |
---|---|---|
newInstance(Object… initargs) | T(泛型) | 通过给构造方法利用指定参数创建一个该类的对象,如果未设置参数则表示采用默认无参数的构造方法 |
getModifiers() | int | 获得可以解析出该构造方法所采用修饰符的整数 |
getName() | String | 返回此构造函数的名称。 |
getParameterTypes() | Class<?>[] | 返回一个 Class对象的数组获得各个参数的类型 |
getExceptionTypes() | Class<?>[] | 返回一个 Class对象的数组获得各个异常的类型 |
isVarArgs() | boolean | 查看该构造方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false |
setAccessible(boolean flag) | void | 如果该构造方法的权限为private,默认为不允许通过利用反射newInstance方法创建对象。如果先执行该方法,并将入口参数设为true,则允许创建 |
package com.test;
public class Example {
String s;
int id;
double d;
public Example() {
}
public Example(String s) {
this.s = s;
}
private Example(String s, int id, double d) {
this.s = s;
this.id = id;
this.d = d;
}
@Override
public String toString() {
return "Example { s="+s+",id="+id+",d="+d+"}";
}
}
package com.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
public class TestReflect {
public static void main(String[] args) {
try {
Class c =Class.forName("com.test.Example");
System.out.println("获取所有构造方法");
Constructor cons[]=c.getDeclaredConstructors(); //获取所有构造方法
for(Constructor con:cons){
System.out.print(Modifier.toString(con.getModifiers())+" "); //修饰符
System.out.print(con.getName()+" ("); //构造方法名
Class[] type=con.getParameterTypes();
for(int i=0;i<type.length;i++){
System.out.print(type[i].getSimpleName()+" args ");
if(i<type.length-1){
System.out.print(",");
}
}
System.out.println(") { }");
}
System.out.println("获取指定构造方法");
Constructor con=c.getDeclaredConstructor(String.class);
System.out.print(Modifier.toString(con.getModifiers())+" "); //修饰符
System.out.print(con.getName()+" ("); //构造方法名
Class[] type=con.getParameterTypes();
for(int i=0;i<type.length;i++){
System.out.print(type[i].getSimpleName()+" args ");
if(i<type.length-1){
System.out.print(",");
}
}
System.out.println(") { }");
System.out.println("通过Constructor的newInstance方法创建不同的对象");
//创建不同的对象
Constructor cs1=c.getDeclaredConstructor(); //无参数的构造方法
Object obj=cs1.newInstance();
System.out.println(obj.toString());
Constructor cs2=c.getDeclaredConstructor(String.class); //有参数的构造方法
obj=cs2.newInstance("反射");
System.out.println(obj.toString());
Constructor cs3=c.getDeclaredConstructor(String.class,int.class,double.class); ///有参数的构造方法
cs3.setAccessible(true); //因为三个参数的构造方法是私有的 所以通过setAccessible获取操作权限
obj=cs3.newInstance("李明",20,180.9);
System.out.println(obj.toString());
} catch (ClassNotFoundException | NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
输出结果:
获取所有构造方法
private com.test.Example (String args ,int args ,double args ) { }
public com.test.Example (String args ) { }
public com.test.Example () { }
获取指定构造方法
public com.test.Example (String args ) { }
通过Constructor的newInstance方法创建不同的对象
Example { s=null,id=0,d=0.0}
Example { s=反射,id=0,d=0.0}
Example { s=李明,id=20,d=180.9}
Field 访问成员变量
通过Class的方法可以返回Field类型的对象或者数组
每个Field对象代表一个成员变量,利用Field对象可以操纵相应的成员变量
Class的相应方法如下
方法 | 返回值 | 说明 |
---|---|---|
getFields() | Field型数组 | 获得所有权限为public的成员变量 |
getFields(String name) | Field对象 | 获得权限为public的指定成员变量 |
getDeclaredFields() | Field型数组 | 获得所有成员变量,按声明顺序返回 |
getDeclaredFields() | Field对象 | 获得指定成员变量 |
Class c=Example.class
Field f=c.getField("name"); //参数传入成员变量的名字 比如Example里面有个名字为name的成员变量
Field类的常用方法
方法 | 返回值 | 说明 |
---|---|---|
getModifiers() | int | 获得可以解析出该成员变量所采用修饰符的整数 |
getName() | String | 返回此成员变量的名称。 |
getTypes | Class<?> | 获得表示该成员变量类型的Class对象 |
get(Object obj) | Object | 获得指定对象obj中成员变量的值,返回值为Object型 |
getBoolean(Object obj) boolean | 获得指定对象obj中成员变量类型为boolean的值 | |
getFloat(Object obj) | float | 获得指定对象obj中成员变量类型为float的值 |
getDouble(Object obj) | double | 获得指定对象obj中成员变量类型为double的值 |
getInt(Object obj) | int | 获得指定对象obj中成员变量类型为int的值 |
set(Object obj, Object value) | void | 将指定对象obj中成员变量的值设置为value |
setBoolean(Object obj, boolean z) | void | 将指定对象obj中成员变量为boolean类型的值设置为z |
setFloat(Object obj, float f) | void | 将指定对象obj中成员变量为float 类型的值设置为z |
setDouble(Object obj, double d) | void | 将指定对象obj中成员变量为double 类型的值设置为d |
setInt(Object obj, int i) | void | 将指定对象obj中成员变量为int 类型的值设置为i |
setAccessible(boolean flag) | void | 如果该成员变量的权限为private,默认为不允许通过利用反射newInstance方法访问成员变量。如果先执行该方法,并将入口参数设为true,则允许访问 |
package com.test;
package com.test;
public class Example {
public String str="XXX";
public int id=1;
private double pi=3.14;
}
package com.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
public class FieldReflect {
public static void main(String[] args) {
try {
Class c=Example.class;
Field[] fs= c.getDeclaredFields();
System.out.println("----输出所有成员变量---");
for (Field f:fs){
System.out.print(Modifier.toString(f.getModifiers())+" ");
System.out.print(f.getType().getSimpleName()+" ");
System.out.print(f.getName()+" ");
System.out.println();
}
System.out.println("----输出指定成员变量----");
Field fd=c.getDeclaredField("pi");
System.out.print(Modifier.toString(fd.getModifiers())+" ");
System.out.print(fd.getType().getSimpleName()+" ");
System.out.print(fd.getName()+" ");
System.out.println();
System.out.println("-----获取值和修改值----");
Constructor con=c.getDeclaredConstructor();
Example e= (Example) con.newInstance(); //创造对象
Field f=c.getDeclaredField("pi");
f.setAccessible(true);
System.out.println("获取值");
System.out.println(f.get(e));
f.set(e,3.14159126); //修改属性值
System.out.println("修改后的值");
System.out.println(f.get(e)); //修改属性值
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
输出结果:
----输出所有成员变量---
public String str
public int id
private double pi
----输出指定成员变量----
private double pi
-----获取值和修改值----
获取值
3.14
修改后的值
3.14159126
Method类 (访问方法)
通过Class的方法可以返回Method类型的对象或者数组
每个Method对象代表一个成员变量,利用Method对象可以操纵相应的成员变量
Class相应方法如下
方法 | 返回值 | 说明 |
---|---|---|
getMethods() | Method型数组 | 获得所有权限为public的方法 |
getMethod(String name,Class<?> …parameterTypes | Method对象 | 获得权限为public的指定方法 |
getDeclaredMethods() | Method型数组 | 获得所有方法,按声明顺序返回 |
getDeclaredMethod(String name,Class<?> …parameterTypes | Method对象 | 获得指定方法 |
Class c=Example.class
Method m1=c.getMethod("name1"); // 无参数的方法 比如Example里面有个名字为name1的无参数成员方法
Method m2=c.getMethod("name2",String.class,int.class); //有参数的方法 比如Example里面有个名字为name2的有参数成员方法参数类型为String和int
Method类常用方法
方法名 | 返回值 | 说明 |
---|---|---|
getModifiers() | int | 获得可以解析出该方法所采用修饰符的整数 |
getReturnType | Class<?> | 返回一个 Class对象的数组获得返回类型 |
getName() | String | 返回此方法的名称。 |
getParameterTypes() | Class<?>[] | 返回一个 Class对象的数组获得各个参数的类型 |
getExceptionTypes() | Class<?>[] | 返回一个 Class对象的数组获得各个异常的类型 |
isVarArgs() | boolean | 查看该方法是否允许带有可变数量的参数,如果允许则返回true,否则返回false |
invoke(Object obj, Object… args) | Object | 在具有指定参数的方法对象上调用此方法 |
setAccessible(boolean flag) | void | 如果该方法的权限为private,默认为不允许通过利用反射newInstance方法创建对象。如果先执行该方法,并将入口参数设为true,则允许创建 |
package com.test;
public class Example {
public String str="XXX";
public int id=1;
private double pi=3.14;
public String getStr(){
return this.str;
}
public int getId() {
return id;
}
public double getPi() {
return pi;
}
public void setStr(String str) {
this.str = str;
}
public void setId(int id) {
this.id = id;
}
public void setPi(double pi) {
this.pi = pi;
}
}
package com.test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class MethodReflect {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class c=Example.class;
Method[] methods=c.getDeclaredMethods();
System.out.println("----输出所有方法----");
for (Method me:methods){
System.out.print(Modifier.toString(me.getModifiers())+" ");
System.out.print(me.getReturnType().getSimpleName()+" ");
System.out.print(me.getName()+"(");
Class[] types=me.getParameterTypes();
for(int i=0;i<types.length;i++){
System.out.print(types[i].getSimpleName()+" arg");
if(i<types.length-1){
System.out.print(",");
}
}
System.out.print(") ");
Class[] exceptions=me.getExceptionTypes();
if(exceptions.length>0) {
System.out.print("throws ");
for (int i = 0; i < exceptions.length; i++) {
System.out.print(exceptions[i].getSimpleName());
if (i < exceptions.length - 1) {
System.out.print(",");
}
}
}
System.out.println("{ }");
}
System.out.println("---执行方法---");
Constructor con=c.getConstructor();
Example e= (Example) c.newInstance();
Method m=c.getDeclaredMethod("getId");
m.setAccessible(true);
System.out.println(m.invoke(e)); //输出返回值
}
}
输出结果:
----输出所有方法----
public int getId() { }
public void setStr(String arg) { }
public void setId(int arg) { }
public void setPi(double arg) { }
public String getStr() { }
public double getPi() { }
---执行方法---
1
访问注释信息
如果将Annotation的元注释 @Retention设置为RetentionPoilcy.RUNTIME(写入JVM),就可以获取相关的Annotation信息
Constructor,Field,Method均有反射Annotation信息的方法
方法 | 说明 |
---|---|
isAnnotationPresent(Class<? extends Annotation> annotationClass | 判断是否添加了指定的Annotation信息 |
getAnnotation(Class annotationClass) | 获得指定的Annotation类型 |
getAnnotations() | 返回所有注解,返回一个Annotation数组 |
public Student{
String name; //姓名
int id; //学号
int age; //年龄
double height; //身高
}
上面的代码中使用"//"符号来注释代码,但是在运行时,是无法看到这些注解的。如果要在运行时获得注解信息,就需要反射Annnotation
package com.test;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface StudentAnnotation {
String remark() default ""; //备注
boolean enable() default true; //属性是否启用
}
package com.test;
public class Student {
@StudentAnnotation(remark = "学生姓名")
public String name; //姓名
@StudentAnnotation(remark = "学号")
public int id; //学号
@StudentAnnotation(remark = "年龄")
public int age; //年龄
@Deprecated //注释属性过时
@StudentAnnotation(remark = "身高",enable = false)
public double height; //身高
}
package com.test;
import java.lang.reflect.Field;
public class AnnotationReflect {
public static void main(String[] args) {
Class c=Student.class;
Field fs[]=c.getDeclaredFields();
for (Field f:fs){
if(f.isAnnotationPresent(StudentAnnotation.class)){ //Annotation被反射,Annotation的@Retention需要设置为RetentionPolicy.RUNTIME
System.out.print("属性"+f.getName()+"的注解: ");
StudentAnnotation sa=f.getAnnotation(StudentAnnotation.class);
System.out.print("备注="+sa.remark()+" ");
System.out.println("属性是否有效="+sa.enable());
}
}
}
}
输出结果:
属性name的注解: 备注=学生姓名 属性是否有效=true
属性id的注解: 备注=学号 属性是否有效=true
属性age的注解: 备注=年龄 属性是否有效=true
属性height的注解: 备注=身高 属性是否有效=false
返回方法参数的Annotation信息要使用getParameterAnnotations(),返回一个Annotation的二维数组
package com.test;
public class Student {
@StudentAnnotation(remark = "学生姓名")
public String name; //姓名
@StudentAnnotation(remark = "学号")
public int id; //学号
@StudentAnnotation(remark = "年龄")
public int age; //年龄
@StudentAnnotation(remark = "成绩",enable = true)
public double score; //成绩
@StudentAnnotation(remark = "构造方法",enable = true)
public Student( @StudentAnnotation(remark = "名字参数") String name, @StudentAnnotation(remark = "学号参数") int id,@StudentAnnotation(remark = "年龄参数")int age,@StudentAnnotation(remark = "成绩参数")double score){
this.name=name;
this.id=id;
this.age=age;
this.score=score;
}
@StudentAnnotation(remark = "获得学生信息")
public String getStudentInfo(){
return "学生姓名:"+name+"学号:"+id+"年龄:"+age+"成绩:"+score;
}
}
package com.test;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Reflect {
public static void main(String[] args) {
Class c=Student.class;
try {
Field fs[]=c.getDeclaredFields();
System.out.println("-------成员属性Annotation-----");
for (Field f:fs){
if(f.isAnnotationPresent(StudentAnnotation.class)){ //Annotation被反射,Annotation的@Retention需要设置为RetentionPolicy.RUNTIME
System.out.print("属性"+f.getName()+"的注解: ");
StudentAnnotation sa=f.getAnnotation(StudentAnnotation.class);
System.out.print("备注="+sa.remark()+" ");
System.out.println("属性是否有效="+sa.enable());
}
}
Constructor con=c.getConstructor(String.class, int.class, int.class, double.class);
System.out.println("---------构造方法Annotation-----");
if(con.isAnnotationPresent(StudentAnnotation.class)){
StudentAnnotation sa= (StudentAnnotation) con.getAnnotation(StudentAnnotation.class);
System.out.println(sa.remark()+" "+sa.enable());
}
System.out.println("---------构造方法参数Annotation-------");
Annotation[][] types=con.getParameterAnnotations(); //参数的Annotation,返回二维数组
for(int i=0;i<types.length;i++){
for(int j=0;j<types[i].length;j++){
StudentAnnotation sa= (StudentAnnotation) types[i][j];
System.out.print(" 参数备注="+sa.remark());
// System.out.println("参数s "+sa.enable());
}
}
System.out.println();
System.out.println("--------方法Annotation-------");
Method m=c.getDeclaredMethod("getStudentInfo");
if(m.isAnnotationPresent(StudentAnnotation.class)){
StudentAnnotation sa=m.getAnnotation(StudentAnnotation.class);
System.out.println("方法备注="+sa.remark()+" 方法是否有效="+sa.enable());
}
Annotation[][] methodtype=m.getParameterAnnotations();
if(methodtype.length>0)
for(int i=0;i<methodtype.length;i++){
for(int j=0;j<methodtype[i].length;j++){
StudentAnnotation sa= (StudentAnnotation) types[i][j];
System.out.print(" 参数备注="+sa.remark());
// System.out.println("参数s "+sa.enable());
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
}
输出结果:
-------成员属性Annotation-----
属性name的注解: 备注=学生姓名 属性是否有效=true
属性id的注解: 备注=学号 属性是否有效=true
属性age的注解: 备注=年龄 属性是否有效=true
属性score的注解: 备注=成绩 属性是否有效=true
---------构造方法Annotation-----
构造方法 true
---------构造方法参数Annotation-------
参数备注=名字参数 参数备注=学号参数 参数备注=年龄参数 参数备注=成绩参数
--------方法Annotation-------
方法备注=获得学生信息 方法是否有效=true
访问泛型
Java采用泛型擦除的机制来引入泛型。Java中的泛型仅仅是给编译器javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是,一旦编译完成,所有的和泛型有关的类型全部擦除。
为了通过反射操作这些类型以迎合实际开发的需要,Java就新增ParameterizedType,GenericArrayType,TypeVariable 和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。
ParameterizedType: 表示一种参数化的类型,比如Collection
• GenericArrayType: 表示一种元素类型是参数化类型或者类型变量的数组类型
• TypeVariable: 是各种类型变量的公共父接口
• WildcardType: 代表一种通配符类型表达式
1.获取指定方法参数泛型信息
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class test {
public void dosome(Map<Integer,String> map,List<String> list){
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Method method=Class.forName("test").getMethod("dosome",Map.class,List.class);
Type[] types= method.getGenericParameterTypes(); //获得参数
for(Type type:types){
System.out.print(type+"参数的泛型:");
if(type instanceof ParameterizedType){
Type[] genericTypes=((ParameterizedType) type).getActualTypeArguments();
for(Type genericType:genericTypes){
System.out.println("泛型类型"+genericType);
}
}
}
}
}
输出结果:
java.util.Map<java.lang.Integer, java.lang.String>参数的泛型:泛型类型class java.lang.Integer
泛型类型class java.lang.String
java.util.List<java.lang.String>参数的泛型:泛型类型class java.lang.String
2.获得指定方法返回值泛型
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
public class test {
public Map<Integer,String> dosome(){
System.out.println("do");
return null;
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Method method=Class.forName("ReflectionLearn.test").getMethod("dosome",null);
Type type= method.getGenericReturnType(); //获得返回值
if(type instanceof ParameterizedType){
Type[] genericTypes=((ParameterizedType) type).getActualTypeArguments();
for(Type genericType:genericTypes){
System.out.println(genericType);
}
}
}
}
输出结果:
class java.lang.Integer
class java.lang.String