文章目录
- 1.反射机制概述
- 2.获取Class的四种方式
- 3.通过反射机制实例化对象*
- 4.反射机制结合配置文件灵活实例化对象*
- 5.java.lang.reflect.Field
- 5.1反编译类中的所有字段/属性
- 5.2 通过反射机制给属性赋值*
- 6.java.lang.reflect.Method
- 6.1反编译类中的所有方法
- 6.2 通过反射机制调用方法*
- 7.java.lang.reflect.Constructor
- 7.1 反编译类的构造方法
- 7.2 通过反射机制调用构造方法*
- 8.通过反射模拟实现框架的一部分
- 9.类加载
- 9.1 获取Class的第四种方式
- 9.2 类加载器
- 9.3 双亲委派机制
- 10.反射与泛型
- 10.1 通过反射获取父类的泛型
- 10.2 通过反射获取接口的泛型
- 10.3 通过反射获取属性上的泛型
- 10.4 通过反射获取方法参数和返回值上的泛型
- 10.5 通过反射获取构造方法参数的泛型
1.反射机制概述
反射机制是JDK中的一套类库,这套类库可以帮助我们操作/读取class文件,反射机制可以让程序更灵活,后期学习的大量java框架底层都是基于反射机制实现的,需要能够熟练地使用反射机制中的方法。
反射机制最核心的几个类:
java.lang.Class
:Class类型的实例代表硬盘上的某个class文件,或者说代表一种类型,并且需要注意的是某种类型的class文件在内存中只有一份,无论以何种方式获取到的都是同一个;java.lang.reflect.Field
:Field类型的实例代表类中的属性/字段;java.lang.reflect.Constructor
:Constructor类型的实例代表类中的构造方法;java.lang.refelct.Method
: Method类型的实例代表类中的方法。
2.获取Class的四种方式
第一种方式: Class c = Class.forName("完整的全限定类名");
①全限定类名是带有包名的;
②如果是lang包下的,java.lang也不能省略;
③参数为字符串参数;
④如果类不存在,运行时会报异常:java.lang.ClassNotFoundException
;
⑤这个方法的执行会导致类加载。
第二种方式: 通过类的引用调用:Class c = 引用.getClass();
第三种方式: 在java中任何一种类型,包括基本数据类型,都有.class属性,用这个属性可以获取对应的Class实例:Class c = 类名.class;
第四种方式: 通过类加载器获取(具体见后9.1)
示例代码:
User类:
package reflecttest;
public class User {
}
package reflecttest;
public class ReflectTest01 {
public static void main(String[] args) throws ClassNotFoundException {
//第一种方式:Class.forName("完整的全限定类名")
//stringClass代表String类型,代表硬盘上的String.class文件
Class stringClass = Class.forName("java.lang.String");
//获取User类型
Class userClass = Class.forName("reflecttest.User");
//第二种方式,obj.getClass()
String s = "反射机制";
Class stringClass2 = s.getClass();
//某种类型的字节码文件在内存中只有一份
//stringClass 和 stringClass2 都代表了同一种类型:String类型
System.out.println(stringClass == stringClass2); //true
User user = new User();
Class userClass2 = user.getClass();
System.out.println(userClass == userClass2); //true
//第三种方式:类名.class
Class intClass = int.class;
Class stringClass3 = String.class;
Class userClass3 = User.class;
System.out.println(userClass3 == userClass); //true
}
}
3.通过反射机制实例化对象*
假设userClass为获取到的User类型,则可以通过userClass.newInstance()
实例化User对象,其底层是通过调用User类的无参构造方法完成对象的实例化。
注意: 要使用newInstance()
方法的话,必须要保证对应类中存在无参构造方法,如果没有无参构造方法,则会出现异常:java.lang.InstantiationException
。
此外,newInstance()
方法从java9开始已过时。
修改User类:
package reflecttest;
public class User {
static {
System.out.println("静态代码块调用了!");
}
public User(){
System.out.println("无参构造方法调用了!");
}
}
示例代码:
package reflecttest;
public class ReflectTest02 {
public static void main(String[] args) throws Exception {
//获取User类型,会进行类加载,类中若有静态代码块会执行
Class userClass = Class.forName("reflecttest.User");
//通过userClass创建User实例,返回Object类型,需要向下转型
//必须保证User类中有无参构造方法
User user = (User)userClass.newInstance();
System.out.println(user);
//每次调用创建的是不同的对象实例
User user2 = (User)userClass.newInstance();
System.out.println(user2);
System.out.println(user == user2);
}
}
运行结果:
4.反射机制结合配置文件灵活实例化对象*
通过此方式可以做到对象的动态创建,只需要修改属性配置文件就可以完成不同对象的实例化。
classInfo.properties配置文件:
className = reflecttest.User
测试代码(User同上):
package reflecttest;
import java.util.ResourceBundle;
public class ReflectTest03 {
public static void main(String[] args) throws Exception {
//资源绑定器
ResourceBundle resourceBundle = ResourceBundle.getBundle("reflecttest.classInfo");
//通过属性配置文件的key获取value
String className = resourceBundle.getString("className");
//通过反射机制实例化对象
Class objClass = Class.forName(className);
Object o = objClass.newInstance();
System.out.println(o);
}
}
运行结果:
classInfo.properties配置文件:
className = java.util.Date
测试代码不变,运行结果:
5.java.lang.reflect.Field
Vip类:
package reflecttest;
public class Vip {
public String name;
private int age;
protected boolean sex;
int accountId;
public static String grade = "黄金Vip";
public static final String dec = "描述";
}
测试代码:
package reflecttest;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* java.lang.reflect.Field 代表的是一个类中的字段/属性
*/
public class ReflectTest04 {
public static void main(String[] args) throws ClassNotFoundException {
//获取Vip类
Class vipClass = Class.forName("reflecttest.Vip");
System.out.println("获取Vip类中所有public修饰的属性/字段:");
//获取Vip类中所有public修饰的属性/字段
Field[] fields = vipClass.getFields();
//遍历
for (Field field: fields) {
//获取属性名
System.out.println("属性名:"+field.getName());
}
System.out.println("===================================");
System.out.println("获取Vip类中所有属性/字段,包括私有的:");
//获取Vip类中所有属性/字段,包括私有的
Field[] fields1 = vipClass.getDeclaredFields();
//遍历
for (Field field: fields1) {
//获取属性名
System.out.println("属性名:" + field.getName());
//获取属性类型
Class fieldType = field.getType();
System.out.println("属性类型:" + fieldType);
//通过属性类型获取其完整类名
System.out.println("属性类型完整类名:" + fieldType.getName());
//通过属性类型获取其简单类名
System.out.println("属性类型简单类名:" + fieldType.getSimpleName());
//获取属性修饰符
System.out.println("属性修饰符:" + Modifier.toString(field.getModifiers()));
System.out.println();
}
}
}
运行结果:
5.1反编译类中的所有字段/属性
package reflecttest;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ReflectTest05 {
public static void main(String[] args) throws Exception {
//获取Vip类
// Class stringClass = Class.forName("reflecttest.Vip");
Class stringClass = Class.forName("java.util.Date");
//字符串拼接
StringBuilder sb = new StringBuilder();
//获取String类的修饰符
sb.append(Modifier.toString(stringClass.getModifiers()));
sb.append(" class ");
//获取简单类名
sb.append(stringClass.getSimpleName());
sb.append(" extends ");
//获取父类简单类名
sb.append(stringClass.getSuperclass().getSimpleName());
//获取当前类实现的所有接口
Class[] interfaces = stringClass.getInterfaces();
if(interfaces.length > 0){
sb.append(" implements ");
for (int i = 0; i < interfaces.length; i++) {
sb.append(interfaces[i].getSimpleName());
if(i != interfaces.length-1){
sb.append(",");
}
}
}
sb.append(" {\n");
//获取String类中的所有属性字段
Field[] fields = stringClass.getDeclaredFields();
for (Field field: fields) {
sb.append("\t");
sb.append(Modifier.toString(field.getModifiers()));
sb.append(" ");
sb.append(field.getType().getSimpleName());
sb.append(" ");
sb.append(field.getName());
sb.append(";\n");
}
sb.append("}");
System.out.println(sb);
}
}
运行结果:
5.2 通过反射机制给属性赋值*
Customer类:
package reflecttest;
public class Customer {
public String name;
private int age;
}
测试代码:
package reflecttest;
import java.lang.reflect.Field;
public class ReflectTest06 {
public static void main(String[] args) throws Exception {
//获取Customer类
Class customerClass = Class.forName("reflecttest.Customer");
//创建对象
Object o = customerClass.newInstance(); //这里可以向下转型也可以不转型
//获取对应的Field
Field nameField = customerClass.getField("name");
//修改对应的Field的值
//三要素:给哪个对象 的 哪个属性 赋什么值
nameField.set(o,"张三"); //第一参数是指定对象,接收的是Object类型的;第二个参数是需要赋的值
//获取对应的Field的值
System.out.println(nameField.get(o));
//获取ageField,此时age在类中为private的,需要调用getDeclaredField方法获取;且由于私有,无法直接赋值,需要先打破封装
Field ageField = customerClass.getDeclaredField("age");
//调用方法打破封装
ageField.setAccessible(true);
//赋值
ageField.set(o,23);
//获取值
System.out.println(ageField.get(o));
}
}
运行结果:
6.java.lang.reflect.Method
UserService类:
package reflecttest;
public class UserService {
public boolean login(String name, String password){
return "admin".equals(name) && "123456".equals(password);
}
public void logout(){
System.out.println("logout...");
}
}
测试代码:
package reflecttest;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
public class ReflectTest07 {
public static void main(String[] args) throws Exception {
//获取UserService类
Class clazz = Class.forName("reflecttest.UserService");
//获取所有声明的方法
Method[] methods = clazz.getDeclaredMethods();
//遍历数组
for (Method method: methods) {
//获取方法修饰符
System.out.println(Modifier.toString(method.getModifiers()));
//获取方法返回值类型
System.out.println(method.getReturnType().getSimpleName());
//获取方法名
System.out.println(method.getName());
System.out.println();
//获取方法的参数列表
//方式一:获取参数列表类型
Class[] parameterTypes = method.getParameterTypes();
for (Class parameterType: parameterTypes) {
System.out.println(parameterType.getSimpleName());
}
System.out.println();
//方式二:获取参数数组
Parameter[] parameters = method.getParameters();
for (Parameter parameter:parameters) {
//获取参数类型
System.out.println(parameter.getType().getSimpleName());
//获取参数名
System.out.println(parameter.getName()); //arg0,arg1,arg2...
}
}
}
}
运行结果:
6.1反编译类中的所有方法
package reflecttest;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
public class ReflectTest08 {
public static void main(String[] args) throws Exception {
StringBuilder sb = new StringBuilder();
Class clazz = Class.forName("reflecttest.UserService");
//获取类的修饰符
sb.append(Modifier.toString(clazz.getModifiers()));
sb.append(" class ");
//获取类名
sb.append(clazz.getSimpleName());
sb.append(" extends ");
//获取父类名
sb.append(clazz.getSuperclass().getSimpleName());
//获取父接口名
Class[] interfaces = clazz.getInterfaces();
if(interfaces.length > 0){
sb.append(" implements ");
for (int i = 0; i < interfaces.length; i++) {
sb.append(interfaces[i].getSimpleName());
if(i < interfaces.length - 1){
sb.append(",");
}
}
}
sb.append(" {\n");
//获取所有声明的方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
sb.append("\t");
//获取修饰符
sb.append(Modifier.toString(method.getModifiers()));
sb.append(" ");
//获取返回值类型
sb.append(method.getReturnType().getSimpleName());
sb.append(" ");
//获取方法名
sb.append(method.getName());
sb.append("(");
//获取参数列表
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length ; i++) {
//获取参数类型
sb.append(parameters[i].getType().getSimpleName());
sb.append(" ");
//获取参数名
sb.append(parameters[i].getName());
if(i < parameters.length - 1){
sb.append(",");
}
}
sb.append(")\n");
}
sb.append("}");
System.out.println(sb);
}
}
运行结果:
6.2 通过反射机制调用方法*
package reflecttest;
import java.lang.reflect.Method;
public class ReflectTest09 {
public static void main(String[] args) throws Exception {
//获取UserService类
Class clazz = Class.forName("reflecttest.UserService");
//使用反射机制创建对象
Object userService = clazz.newInstance();
//获取login方法,需要传入方法名和所有参数类型
Method login = clazz.getDeclaredMethod("login", String.class, String.class);
//调用一个方法需要四个要素:
//调用 哪个对象 的 哪个方法,传什么参数,返回什么值
Object retValue = login.invoke(userService, "admin", "123456");
System.out.println(retValue);
//获取logout方法,需要传入方法名和所有参数类型
Method logout = clazz.getDeclaredMethod("logout");
logout.invoke(userService);
}
}
运行结果:
7.java.lang.reflect.Constructor
7.1 反编译类的构造方法
Student类:
package reflecttest;
public class Student {
//编号
private int id;
//姓名
private String name;
//年级
private String grade;
public Student() {
}
public Student(int id) {
this.id = id;
}
public Student(int id, String name) {
this.id = id;
this.name = name;
}
public Student(int id, String name, String grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", grade='" + grade + '\'' +
'}';
}
}
反编译代码:
package reflecttest;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
public class ReflectTest10 {
public static void main(String[] args) throws Exception{
//获取Student类
Class studentClass = Class.forName("reflecttest.Student");
//字符串拼接
StringBuilder sb = new StringBuilder();
//获取类的修饰符
sb.append(Modifier.toString(studentClass.getModifiers()));
sb.append(" class ");
//获取类名
sb.append(studentClass.getSimpleName());
sb.append(" extends ");
//获取父类名
sb.append(studentClass.getSuperclass().getSimpleName());
//获取父接口名
Class[] interfaces = studentClass.getInterfaces();
if(interfaces.length > 0){
sb.append(" implements ");
for (int i = 0; i < interfaces.length; i++) {
sb.append(interfaces[i].getSimpleName());
if(i < interfaces.length - 1){
sb.append(",");
}
}
}
sb.append(" {\n");
//获取所有声明的构造方法
Constructor[] constructors = studentClass.getDeclaredConstructors();
for (int i = 0; i < constructors.length; i++) {
sb.append("\t");
//获取构造方法修饰符
sb.append(Modifier.toString(constructors[i].getModifiers()));
sb.append(" ");
//获取构造方法名
sb.append(constructors[i].getName());
sb.append("(");
//获取构造方法参数列表
Parameter[] parameters = constructors[i].getParameters();
for (int j = 0; j < parameters.length; j++) {
//获取参数类型
sb.append(parameters[j].getType().getSimpleName());
sb.append(" ");
//获取参数名(arg0,arg1,arg2...)
sb.append(parameters[j].getName());
if (j < parameters.length - 1){
sb.append(", ");
}
}
sb.append(")\n");
}
sb.append("}");
System.out.println(sb);
}
}
运行结果:
7.2 通过反射机制调用构造方法*
package reflecttest;
import java.lang.reflect.Constructor;
public class ReflectTest11 {
public static void main(String[] args) throws Exception{
//获取Student类
Class studentClass = Class.forName("reflecttest.Student");
//获取无参构造方法
Constructor defaultCons = studentClass.getDeclaredConstructor();
//通过无参构造方法创建对象
Object o1 = defaultCons.newInstance();
System.out.println(o1);
//获取一个参数构造方法
Constructor oneParaCons = studentClass.getDeclaredConstructor(int.class);
Object o2 = oneParaCons.newInstance(2201);
System.out.println(o2);
//获取三个参数构造方法
Constructor threeParaCons = studentClass.getDeclaredConstructor(int.class, String.class, String.class);
Object o3 = threeParaCons.newInstance(2301, "张三", "高三");
System.out.println(o3);
}
}
运行结果:
8.通过反射模拟实现框架的一部分
UserService类:
package reflecttest;
public class UserService {
public boolean login(String name, String password){
return "admin".equals(name) && "123456".equals(password);
}
public void logout(){
System.out.println("logout...");
}
}
package reflecttest;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ResourceBundle;
/**
* 使用反射模拟实现框架的一部分
*/
public class ReflectTest12 {
public static void main(String[] args) throws Exception{
//读取配置文件
ResourceBundle resourceBundle = ResourceBundle.getBundle("reflecttest.config");
//获取配置信息
String className = resourceBundle.getString("className");
String methodName = resourceBundle.getString("methodName");
String parameterType = resourceBundle.getString("parameterType");
String parameterValue = resourceBundle.getString("parameterValue");
//获取类并创建对象
Class clazz = Class.forName(className);
Constructor defaultCons = clazz.getDeclaredConstructor();
Object o = defaultCons.newInstance();
//将参数类型由字符串转为对应的类
String[] strparameterTypes = parameterType.split(",");
Class[] classparameterTypes= new Class[strparameterTypes.length];
for (int i = 0 ; i < strparameterTypes.length ; i++) {
classparameterTypes[i] = Class.forName(strparameterTypes[i]);
}
//获取方法
Method method = clazz.getDeclaredMethod(methodName, classparameterTypes);
String[] strparameterValues = parameterValue.split(",");
//调用方法
Object retValue = method.invoke(o, strparameterValues);
System.out.println(retValue);
}
}
运行结果:
9.类加载
类加载的过程:
- 装载(loading):类加载器负责将类的class文件读入内存,并创建一个java.lang.Class对象;
- 连接(linking)
①验证(Verify):确保加载类的信息符合JVM规范。
②准备(Prepare):正式为静态变量在方法区中开辟存储空间并设置默认值。
public static int k = 10; 此时:k会赋值0
public static final int f = 10; 此时: f会赋值10
③解析(Resolve):将虚拟机常量池内的符号引用替换为直接引用(地址)的过程。 - 初始化(initialization):静态变量赋值,静态代码块执行
对应图:
低版本的JDK中对应类加载器的名字:
启动类加载器:负责加载rt.jar,包含java的核心类,比如String;
扩展类加载器:负责加载ext/*.jar中的类,java的扩展类;
系统类加载器:负责加载classpath中的类,比如自定义类。
9.1 获取Class的第四种方式
通过类加载器获取:
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
Class clazz = classLoader.loadClass(“全限定类名”);
Class.forName和classLoader.loadClass()的区别?
- Class.forName():类加载时会进行初始化。
- classLoader.loadClass():类加载时不会进行初始化,直到第一次使用该类。
测试代码:
Animal类:
package reflecttest;
public class Animal {
static {
System.out.println("静态代码块执行了!");
}
public Animal(){
System.out.println("无参构造方法执行了!");
}
}
package reflecttest;
public class ReflectTest13 {
public static void main(String[] args) throws Exception {
//获取类加载器对象(获取的是系统类加载器/应用类加载器,这个类加载器负责加载classpath中的class文件)
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//加载类,但是这个类加载过程只完成了类加载的前两步(装载和连接),第三步初始化没做
//在第一次使用类的时候才会进行初始化
Class loadClass = systemClassLoader.loadClass("reflecttest.Animal");
}
}
运行结果:
package reflecttest;
public class ReflectTest13 {
public static void main(String[] args) throws Exception {
//获取类加载器对象(获取的是系统类加载器/应用类加载器,这个类加载器负责加载classpath中的class文件)
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
//加载类,但是这个类加载过程只完成了类加载的前两步(装载和连接),第三步初始化没做
//在第一次使用类的时候才会进行初始化
Class loadClass = systemClassLoader.loadClass("reflecttest.Animal");
System.out.println(loadClass.newInstance());
}
}
运行结果:
package reflecttest;
public class ReflectTest13 {
public static void main(String[] args) throws Exception {
Class aClass = Class.forName("reflecttest.Animal");
}
}
运行结果:
9.2 类加载器
虚拟机内部提供了三种类加载器(Java9+):
- 启动类加载器(BootstrapClassLoader):加载Java最核心的类,例如String;
- 平台类加载器(PlatformClassLoader):加载Java平台扩展的类库,例如解析XML的;
- 应用类加载器(AppClassLoader):加载classpath中的。
同时我们还可以自定义一个类加载器(UserClassLoader)。
获取类加载器可以通过 getParent()
方法一级一级获取。
package reflecttest;
public class ReflectTest14 {
public static void main(String[] args) {
//通过自定义的类获取的类加载器是:应用类加载器
ClassLoader classLoader1 = ReflectTest14.class.getClassLoader();
System.out.println("当前应用类加载器:" + classLoader1);
//第二种获取应用类加载器的方式
ClassLoader classLoader2 = ClassLoader.getSystemClassLoader();
System.out.println("当前应用类加载器:" + classLoader2);
//第三种获取应用类加载器的方式
ClassLoader classLoader3 = Thread.currentThread().getContextClassLoader();
System.out.println("当前应用类加载器:" + classLoader3);
//通过getParent()方法可以获取当前类加载器的“父 类加载器”
//获取平台类加载器
System.out.println("当前平台类加载器:" + classLoader1.getParent());
//获取启动类加载器
//启动类加载器负责加载的是Java的核心类库,这个类加载器的名字看不到,直接输出的话结果是null
System.out.println(classLoader1.getParent().getParent());
}
}
运行结果:
9.3 双亲委派机制
某个类加载器接收到加载类的任务时,通常委托给“父 类加载器”完成加载。
最“父 类加载器”无法加载时,一级一级向下委托加载任务。
作用:
- 保护程序的安全。
- 防止类加载重复。
10.反射与泛型
10.1 通过反射获取父类的泛型
Person类:
package reflecttest;
/**
* 在类上定义泛型
* @param <K>
* @param <Y>
* @param <Z>
*/
public class Person<K,Y,Z> {
}
Doctor类继承Person类:
package reflecttest;
public class Doctor extends Person<Integer,Double,String> {
}
测试代码:
package reflecttest;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class ReflectTest15 {
public static void main(String[] args) {
//获取类
Class<Doctor> doctorClass= Doctor.class;
//获取当前类的父类泛型
Type genericSuperclass = doctorClass.getGenericSuperclass();
//如果当前类的父类没有使用泛型,则instanceof Class为true
System.out.println(genericSuperclass instanceof Class);
//如果当前类的父类使用了泛型,则instanceof ParameterizedType为true
System.out.println(genericSuperclass instanceof ParameterizedType);
System.out.println("=======================");
//如果父类使用了泛型
if (genericSuperclass instanceof ParameterizedType) {
//转换为参数化类型
ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;
//获取泛型数组
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
//遍历数组
for (Type type: actualTypeArguments) {
//获取泛型的具体类型名
System.out.println(type.getTypeName());
}
}
}
}
运行结果:
10.2 通过反射获取接口的泛型
Flyable接口:
package reflecttest;
public interface Flyable<K,V> {
}
Bird类:
package reflecttest;
public class Bird implements Flyable<Integer, String>, Comparable<Bird>{
@Override
public int compareTo(Bird o) {
return 0;
}
}
测试代码:
package reflecttest;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class ReflectTest16 {
public static void main(String[] args) {
//获取类
Class<Bird> birdClass = Bird.class;
//获取当前类实现的接口上的泛型
Type[] genericInterfaces = birdClass.getGenericInterfaces();
//遍历
for (Type type: genericInterfaces) {
//如果使用了泛型
if(type instanceof ParameterizedType){
//转换为参数化类型
ParameterizedType parameterizedType = (ParameterizedType) type;
//获取泛型数组
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
//遍历数组
for (Type t:actualTypeArguments) {
System.out.println(t.getTypeName());
}
}
}
}
}
运行结果:
10.3 通过反射获取属性上的泛型
Flower类:
package reflecttest;
import java.util.HashMap;
public class Flower {
private HashMap<Integer,String> map;
}
测试代码:
package reflecttest;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class ReflectTest17 {
public static void main(String[] args) throws Exception {
//获取类
Class<Flower> flowerClass = Flower.class;
//获取指定属性,注意,由于这里map是私有的,需要使用getDeclaredField方法
Field mapField = flowerClass.getDeclaredField("map");
//获取属性上的泛型
Type mapFieldGenericType = mapField.getGenericType();
//如果使用了泛型
if(mapFieldGenericType instanceof ParameterizedType){
//转换为参数化类型
ParameterizedType fieldGenericType = (ParameterizedType) mapFieldGenericType;
//获取泛型数组
Type[] actualTypeArguments = fieldGenericType.getActualTypeArguments();
//遍历
for (Type t: actualTypeArguments) {
System.out.println(t.getTypeName());
}
}
}
}
运行结果:
10.4 通过反射获取方法参数和返回值上的泛型
Dog类:
package reflecttest;
import java.util.List;
import java.util.Map;
public class Dog {
public Map<String,String> eat(List<String> list){
return null;
}
}
测试代码:
package reflecttest;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
public class ReflectTest18 {
public static void main(String[] args) throws Exception {
//获取类
Class<Dog> dogClass = Dog.class;
//获取方法
Method eatMethod = dogClass.getMethod("eat", List.class);
//获取方法参数上的泛型
Type[] genericParameterTypes = eatMethod.getGenericParameterTypes();
System.out.println(eatMethod.getName() + "方法" + "参数上的泛型:");
//遍历
for (Type type:genericParameterTypes) {
//如果使用了泛型
if(type instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type t:actualTypeArguments) {
System.out.println(t.getTypeName());
}
}
}
//获取方法返回值上的泛型
Type genericReturnType = eatMethod.getGenericReturnType();
System.out.println();
System.out.println(eatMethod.getName() + "方法" + "返回值上的泛型:");
//如果使用了泛型
if(genericReturnType instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type t:actualTypeArguments) {
System.out.println(t.getTypeName());
}
}
}
}
运行结果:
10.5 通过反射获取构造方法参数的泛型
Phone类:
package reflecttest;
import java.util.Map;
public class Phone {
public Phone(Map<Integer,String> map){
}
}
测试代码:
package reflecttest;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
public class ReflectTest19 {
public static void main(String[] args) throws Exception {
//获取类
Class<Phone> phoneClass = Phone.class;
//获取构造方法
Constructor<Phone> declaredConstructor = phoneClass.getDeclaredConstructor(Map.class);
//获取构造方法参数上的泛型
Type[] genericParameterTypes = declaredConstructor.getGenericParameterTypes();
//遍历
for (Type type:genericParameterTypes) {
//如果使用了泛型
if(type instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) type;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type t:actualTypeArguments) {
System.out.println(t.getTypeName());
}
}
}
}
}
运行结果: