Java 反射
1、什么是反射?
反射 允许对封装类的字段,方法 和 构造函数的信息进行编程访问。(就是可以从类里面拿东西)
| 反射可以得到类的(获取)(从class字节码文件中获取,所以需要先得到类的字节码文件对象) | 功能(解刨) |
|---|---|
| 字段(成员变量) | 获取修饰符、获取名字、获取类型、赋值/获取值 |
| 构造方法 | 获取修饰符、获取名字、获取形参、创建对象 |
| 成员方法 | 获取修饰符、获取名字、获取形参、获取返回值、抛出的异常、获取注解、运行方法 |
2、获取class对象的三种方式
① Class.forName("全类名"); 源代码阶段
②类名 . Class 加载阶段
③对象 . getClass(); (定义在Object这个类中的方法,所以所有对象都有这个方法) 运行阶段
| 源代码阶段 | .java文件通过 javac 编译成 .class文件 |
|---|---|
| 加载阶段 | .class 文件在内存中 加载 |
| 运行阶段 | 在内存中创建类的对象 |
获得class 字节码对象
//全类名 com.xxl.job.admin.fanshe.Student
Class<?> aClass = Class.forName("com.xxl.job.admin.fanshe.Student");
// System.out.println("aClass = " + aClass);
Class<Student> studentClass = Student.class;
// System.out.println("studentClass = " + studentClass);
Student student = new Student();
Class<? extends Student> aClass1 = student.getClass();
// System.out.println("aClass1 = " + aClass1);
3、反射获取 构造方法
/**
* Class 类中用于获取构造器对象的方法
* Constructor<?>[] getConstructors(); 返回所有公共构造方法对象的数组 (公共表示public修饰的构造方法)
* Constructor<?>[] getDeclaredConstructors();返回所有构造方法对象的数组
* Constructor<T> getConstructor(Class<?>... parameterTypes);返回单个公共构造方法对象 (公共表示public修饰的)
* Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);返回单个构造方法对象
*
*
* Constructor类中用于创建对象的方法
* T newInstance(Object... initargs); 根据指定的构造方法创建对象
* setAccessible(boolean flag);设置是否允许访问,私有的属性、方法、构造器都可以访问 true表示允许访问,取消访问检查
*
*/
//利用字节码文件来获取构造方法的 aClass
//获取所有的公共的构造方法
Constructor<?>[] cons = aClass.getConstructors();
for (Constructor<?> con : cons) {
System.out.println("con = " + con);
}
//获取所有的 连带私有的
Constructor<?>[] dec = aClass.getDeclaredConstructors();
for (Constructor<?> constructor : dec) {
System.out.println("constructor = " + constructor);
}
//获取单个的公共的构造方法
Constructor<?> constructor = aClass.getConstructor();
System.out.println("constructor = " + constructor);
//获取单个指定 任意 参数的构造方法
Constructor<?> dc = aClass.getDeclaredConstructor(int.class);
System.out.println("declaredConstructor = " + dc);
3.1、获取权限修饰符的方法
public 对应 1 private 对应 2
protected 对应 4
int modifiers = dc.getModifiers(); // 获取构造方法的修饰符
System.out.println("modifiers = " + modifiers); //输出2
3.2、获取构造方法的参数并分析
getParameters() //获取所有的参数
getParameterCount() //获得参数的个数
getParameterType() //获得参数的类型
3.3、对于私有的构造函数进行创建对象
//假设 dc 是通过 getDeclaredConstructor(String.Class)得到的私有的带有String 类型的构造函数
dc.setAccessible(true); // 表示临时允许访问,取消访问检查 !!!
Object o = dc.newInstance(6);
System.out.println("o = " + o);
4、反射获取 成员变量
/**
* 利用反射获取成员变量
* Class类中用于获取成员变量的方法
* Filed[] getFields();返回所有公共成员变量对象(public修饰的)的数组
* Filed[] getDeclaredFields();返回所有成员变量对象的数组
* Filed getField(String name);返回单个公共成员变量对象(public修饰的)
* Filed getDeclaredField(String name);返回单个成员变量对象
*
* Filed类中用于创建对象的方法
* void set(Object obj, Object value);为对象变量赋值
* Object get(Object obj);获取对象变量的值
*/
//利用反射 获取目标对象的成员变量
//1、获取目标对象的字节码文件对象
Class<?> stu = Class.forName("com.xxl.job.admin.fanshe.Student");
//获取 公共的 成员变量
Field[] fields = stu.getFields();
for (Field field : fields) {
System.out.println("field = " + field);
}
//获取所有的 包括私有的 成员变量
Field[] declaredFields = stu.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println("declaredField = " + declaredField);
}
//获取单个的
Field name = stu.getField("name");
System.out.println("name = " + name);
//获取单个的私有的
Field sex = stu.getDeclaredField("sex");
System.out.println("sex = " + sex);
//获取成员变量的修饰符
int modifiers = sex.getModifiers();
System.out.println("modifiers = " + modifiers);
//获取成员变量名
String name1 = sex.getName();
System.out.println("name1 = " + name1);
//获取成员变量的类型
Class<?> type = sex.getType();
System.out.println("type = " + type);
//获取成员变量记录的值
Student student = new Student(6, "李龙", "男");
sex.setAccessible(true); //因为sex 是私有的,所以需要取消访问检查
Object o = sex.get(student);
System.out.println("o = " + o);
System.out.println("student = " + student);
//修改值 改为女
sex.set(student, "女");
System.out.println("student = " + student);
5、反射获取 成员方法
/**
* 利用反射获取成员方法的方法
* Method[] getMethods();返回所有公共成员方法对象的数组(public修饰的) (包括父类中的 继承的)
* Method[] getDeclaredMethods();返回所有成员方法对象的数组(包括私有的) 不包括父类中的继承的
* Method getMethod(String name, Class<?>... parameterTypes);返回单个公共成员方法对象(包括父类中的继承的)
* Method getDeclaredMethod(String name, Class<?>... parameterTypes);返回单个成员方法对象 (包括私有的)不包括父类中的继承的
*
*
* Method类中用于创建对象的方法
* Object invoke(Object obj, Object... args);运行方法
* 参数1:要调用方法的对象
* 参数2:要调用方法的参数(没有就不写)
* 返回值 :方法的返回值 如果方法没有返回值,就不写
*/
//获取字节码对象
Class<?> cs = Class.forName("com.xxl.job.admin.fanshe.Student");
//获取类中的所有的方法对象 包含父类中所有的
Method[] methods = cs.getMethods();
for (Method method : methods) {
System.out.println("method = " + method);
}
//获取单个的
Method method = cs.getMethod("sleep");
System.out.println("获取单一的方法 = " + method);
//获得方法的修饰符
int modifiers = method.getModifiers();
System.out.println("modifiers = " + modifiers);
//获取方法的名字
String name = method.getName();
System.out.println("方法名字 = " + name);
//获得方法的形参
Method eat = cs.getDeclaredMethod("eat",String.class);
Parameter[] parameters = eat.getParameters();
for (Parameter parameter : parameters) {
System.out.println("parameter = " + parameter);
}
// getParameters() //获取所有的参数
// getParameterCount() //获得参数的个数
// getParameterType() //获得参数的类型
//获得方法抛出的异常
Class<?>[] exceptionTypes = eat.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println("exceptionType = " + exceptionType);
}
//运行得到的方法
Student student = new Student(6, "李龙", "男");
//参数一:方法的调用者
//参数二:方法参数 没有就不写
//返回值 没有就不写
eat.setAccessible(true);
Object result = eat.invoke(student, "李兄");
System.out.println("方法的返回值 = " + result);