一,介绍
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
二,反射原理
反射机制允许 Java 程序在运行时调用Reflection API取得任何类的内部信息(比如成员变量、构造器、成员方法等),并能操作类的实例对象的属性以及方法。
在Java 程序中,JVM 加载完一个类后,在堆内存中就会产生该类的一个 Class 对象,一个类在堆内存中最多只会有一个 Class 对象,这个Class 对象包含了该类的完整结构信息,我们通过这个 Class 对象便可以得到该类的完整结构信息。
三。反射常用的方法和类
1.Class类:
是反射的起点,通过该类,可以获取类的信息,类型,方法,字段
User user=new User();
user.setAge(12);
user.setName("测试");
user.setPhone("18360483743");
var o=user.getClass();
//获取类名(不包含报名)
log.info("输出不带包名的类名{}",o.getSimpleName());
//获取类名(全名)
log.info("输出全名的类名{}",o.getName());
//获取方法名:
var methond=o.getMethods();
var methods=o.getDeclaredMethods();
//获取属性
o.getFields();
o.getDeclaredFields();
对于以上的获取方法名和属性名,我们发现两个都可以,两者的主要区别如下:
1. getMethods():
该方法获取类及父类的所有的公共(public)方法
这包括从父类继承的方法以及在类本身定义的公共方法
返回的是一个包含‘Method’对象的数组
2.getDeclaredMethods():
该方法用于获取类自身定义的所有方法,不包括从父类继承的方法。
这包括类的所有访问修饰符的方法,如公共、受保护、默认(包私有)和私有方法。
返回的是一个包含 Method
对象的数组。
getDeclaredMethods()
通常用于获取类的详细信息,而 getMethods()
用于获取类的公共接口。使用时应根据具体需求选择合适的方法。
2.method类:
用于描述类的方法。你可以使用该类调用类的方法。
User user=new User();
user.setAge(12);
user.setName("测试");
user.setPhone("18360483743");
var o=user.getClass();
var method= o.getMethods();
for(var m:method){
//返回改方法的名称
log.info("方法名称为{}", m.getName());
//返回该方法的返回类型
m.getReturnType();
//返回方法修饰符的整数
int modifiers=m.getModifiers();
log.info("是否是public{}",Modifier.isPublic(modifiers));
log.info("是否是private{}",Modifier.isPrivate(modifiers));
//返回方法的参数类型
var types=m.getParameterTypes();
//返回方法的异常类型
Class<?>[] exceptionTypes = m.getExceptionTypes();
}
最后一个执行方法:
Object invoke(Object obj, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
:
- 在特定对象上调用方法,并传递指定的参数。
- 第一个参数是方法所属的对象,如果是静态方法,则可以传递
null
。 - 第二个参数是方法的参数。
3.Constructor 类
用于描述类的构造方法。你可以使用该类创建新的类实例。
User user=new User();
user.setAge(12);
user.setName("测试");
user.setPhone("18360483743");
var o=user.getClass();
//获取所有的公共构造函数
o.getConstructors();
//获取所有的构造函数,可以是公共,私有或者受保护的构造函数
o.getDeclaredConstructors();
//获取执行类型的构造参数
try {
var instance=o.getDeclaredConstructor(String.class);
//使用此构造方法创建一个新的对象
var obj=instance.newInstance("name");
System.out.println(obj);
//获取改构造函数的参数类型数组
var types=instance.getParameterTypes();
//获取修饰符
var modil=instance.getModifiers();
//获取异常类型
instance.getExceptionTypes();
//检查构造函数是否可访问
instance.isAccessible();
//如果参数类型是int,double,char 则需要使用包装类.class
//int int.class char char.class double double.class
var instance2=o.getConstructor(String.class,int.class);
var obj2=instance2.newInstance("lcy",2);
System.out.println(obj2);
} catch (Exception e) {
throw new RuntimeException(e);
}
4.field类
用于描述类的字段(成员变量)。你可以使用该类获取和修改字段的值。
log.info("字段的名称为{}", field.getName());
//返回字段的类型
log.info("字段类型{}", field.getType());
var value = field.get(user);
log.info("获取字段的值为{}", value);
field.set(user, value + "新");
System.out.println(user);
//获取字段上所有的注解
var annot = field.getAnnotations();