Java基础学习(十八)
Java基础学习(十八):反射
本文为个人学习记录,内容学习自 黑马程序员
概念
-
反射允许对封装类的字段(成员变量)、方法(成员方法)和构造函数(构造方法)的信息进行编程访问
-
作用:
-
获取任意一个类中的所有信息
-
对于成员变量:获取修饰符,获取名字,获取类型,赋值/获取值
-
对于成员方法:获取修饰符,获取名字,获取形参,获取返回值,获取抛出的异常,获取注解,运行方法
-
对于构造方法:获取修饰符,获取名字,获取形参,创建对象
-
-
结合配置文件动态创建对象
-
-
示例:IDEA 在调用成员/变量方法或者填写构造方法的形参时出现的提示都是通过反射达成的
获取 class 对象
-
在使用反射之前,需要先获取字节码文件对象,也即 Class 对象
-
获取 class 对象有三种方式,这三种方式分别应用于 Java 中的三种阶段
- Class.forName("全类名");
- 类名.class;
- 对象.getClass();
-
Java 的三种阶段:
- 源代码阶段:将 Java 文件编译成字节码文件,此时采用第一种获取 class 对象的方式
- 加载阶段:将字节码文件加载到内存中,此时采用第二种获取 class 对象的方式
- 运行阶段:在内存中运行代码,此时采用第三种获取 class 对象的方式
-
示例:
public class Test { public static void main(String[] args) throws ClassNotFoundException { // 方式一 // 全类名 = 包名 + 类名 Class clazz1 = Class.forName("com.victoria.demo.Student"); // 方式二 Class clazz2 = Student.class; // 方式三 Student s = new Student(); Class clazz3 = s.getClass(); } }
-
总结:一般使用第一种方式,只需要作为参数传递 class 对象时采用第二种方式,只有已经有对象时才使用第三种方式
反射获取构造方法
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T> getConstructor(Class<?>... parameterTypes) | 返回单个公共构造方法对象 |
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) | 返回单个构造方法对象 |
示例:
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 1.获取字节码文件对象
Class clazz = Class.forName("com.victoria.demo.Student");
// 2.使用不同方法获取构造方法
// 1)获取全部的公共构造方法
Constructor[] cons1 = clazz.getConstructors();
for (Constructor c : cons1) {
System.out.println(c);
}
// 2)获取全部的构造方法
Constructor[] cons2 = clazz.getDeclaredConstructors();
for (Constructor c : cons2) {
System.out.println(c);
}
// 3)获取单个公共构造方法,输入参数需要和构造方法的形参一一对应
// 例如要获取空参构造方法,输入参数就为空;要获取两个参数的构造方法,输入参数就为这两个参数类型的Class对象
Constructor con1 = clazz.getConstructor();
System.out.println(con1);
Constructor con2 = clazz.getConstructor(String.class, int.class);
System.out.println(con2);
// 3.获取构造方法后,查看修饰符、名字、形参等信息
int modifiers = con2.getModifiers();
int count = con2.getParameterCount();
// 4.获取构造方法后,创建对象
// setAccessible()方法用于临时取消权限校验,用于让私有构造方法也能在此处创建对象
con2.setAccessible(true);
Student stu = (Student) con2.newInstance("a", 18);
System.out.println(stu);
}
}
反射获取成员变量
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有公共成员变量对象的数组 |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
示例:
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
// 1.获取字节码文件对象
Class clazz = Class.forName("com.victoria.demo.Student");
// 2.使用不同方法获取成员变量
// 1)获取全部的公共成员变量
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
// 2)获取全部的成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field field : declaredFields) {
System.out.println(field);
}
// 3)获取单个成员变量,输入参数为成员变量名
Field name = clazz.getDeclaredField("name");
System.out.println(name);
// 3.获取成员变量后,查看修饰符、名字、数据类型等信息
int modifiers = name.getModifiers();
String n = name.getName();
Class<?> type = name.getType();
// 4.获取对象中成员变量记录的值
Student s1 = new Student("a", 18);
name.setAccessible(true);
String value = (String) name.get(s1);
// 5.修改对象中成员变量记录的值
Student s2 = new Student("a", 18);
name.setAccessible(true);
name.set(s2, "b");
}
}
反射获取成员方法
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name, Class<?>... parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name, Class<?>... parameterTypes) | 返回单个成员方法对象 |
示例:
public class Test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// 1.获取字节码文件对象
Class clazz = Class.forName("com.victoria.demo.Student");
// 2.使用不同方法获取成员方法
// 1)获取全部的公共成员方法
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
// 2)获取全部的成员方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
// 3)获取单个成员方法,输入参数为成员方法名和其对应的形参
Method method = clazz.getMethod("setName", String.class);
System.out.println(method);
// 3.获取成员方法后,查看修饰符、名字、形参、抛出的异常等信息
int modifiers = method.getModifiers();
String n = method.getName();
int count = method.getParameterCount();
Class<?>[] exceptionTypes = method.getExceptionTypes();
// 4.运行方法
// invoke()方法第一个参数表示方法的调用者,第二个参数为调用方法时传递的实际参数
Student s = new Student();
method.setAccessible(true);
Object result = method.invoke(s, "aaa");
System.out.println(result);
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)