20、反射:
反射概述:
什么是反射?
反射允许对封装类的字段,方法和构造函数的信息进行编程访问。(API中的描述)
翻译成人话:
反射允许对成员变量,成员方法,构造方法的信息进行编程访问。
反射可以将成员变量,成员方法,构造方法获取出来,再进行操作(比如IDEA中的提示功能,就是反射机制的体现)。
获取class对象的三种方式:
- Class.forName(“全类名”);——这样能获得该类的字节码文件对象
- 类名.class;
- 对象.getClass();——定义再Object类中
这三个对应Java中的三个阶段。
- 源代码阶段——使用Class.forName(“全类名”)
- 加载阶段——类名.class
- 运行阶段——对象.getClass()
什么叫全类名:
就是包名加类名。在IDEA中可以快捷复制,在该类下选中类名右键,看到copy后有个copy reference选项,点击即可。
package com.jiangxian.reflect;
/**
* @author JiangXian~
* @version 1.0
*/
public class MyReflect {
public static void main(String[] args) throws ClassNotFoundException {
// 第一种方式
Class Clazz = Class.forName("com.jiangxian.reflect.Student");
System.out.println(Clazz);
// 第二种方式:
System.out.println(Student.class); // 注意访问权限
// 第三种方式:
System.out.println(new Student().getClass());
}
}
第一种方式最常用,第二种作为参数使用,第三种局限最大必须有对象。
Java中的一个重要思想
万物皆对象!
反射获取构造方法:
规则:
- get表示获取;
- Declared 表示私有;
- 最后的 s 表示所有,为负数型式;
- 若当前获取到的是私有的,必须要临时修改访问权限,否则无法使用。
方法名 | 说明 |
---|---|
Constructor<?>[] getConstructors() | 获得所有的构造(只能public修饰) |
Constructor<?>[] getDeclaredConstructors() | 获得所有的构造(包含private修饰) |
Constructor getConstructor(Class<?>… parameterTypes) | 获取指定构造(只能public修饰) |
Constructor getDeclaredConstructor(Class<?>… parameterTypes) | 获取指定构造(包含private修饰) |
package com.jiangxian.reflect;
import java.lang.reflect.Constructor;
/**
* @author JiangXian~
* @version 1.0
*/
public class MyReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
// 1.获取整体(class 字节码对象)
Class clazz = Class.forName("com.jiangxian.reflect.Student");
// 2. 获取构造器对象
System.out.println("======获取public的=======");
Constructor[] constructors = clazz.getConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
//3. 获取所有构造器对象
System.out.println("======获取所有的=======");
Constructor[] constructors1 = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors1) {
System.out.println(constructor);
}
//4. 获取指定参数的构造器
System.out.println("======获取指定参数的构造器======");
Constructor constructor01 = clazz.getConstructor();
System.out.println(constructor01);
Constructor constructor02 = clazz.getConstructor(String.class, int.class);
System.out.println(constructor02);
Constructor constructor03 = clazz.getDeclaredConstructor(String.class);
System.out.println(constructor03);
}
}
创建对象:
涉及到的方法:newInstance
package com.jiangxian.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @author JiangXian~
* @version 1.0
*/
public class Constructor_ {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName("com.jiangxian.reflect.Student");
// 创建无参的构造器
Constructor con = clazz.getConstructor();
Student stu1 = (Student)con.newInstance();
System.out.println(stu1);
// 创建有参构造器:
Constructor con2 = clazz.getDeclaredConstructor(String.class, int.class);
Student stu2 = (Student)con2.newInstance("John", 1);
System.out.println(stu2);
// 暴力反射(跳过private的限制)
Constructor con3 = clazz.getDeclaredConstructor(String.class);
con3.setAccessible(true);
Student stu3 = (Student)con3.newInstance("JiangXian");
System.out.println(stu3);
}
}
反射获取成员变量:
规则:
- get 表示获取;
- Declared 表示私有;
- 最后的 s 表示所有,复数形式;
- 若获取到的成员变量是私有型式,那么需要临时修改访问权限。
方法名 | 说明 |
---|---|
Field[] getFields() | 返回所有成员变量对象的数组(只能拿public的) |
Field[] getDeclaredFields() | 返回所有成员变量对象的数组,存在就能拿到 |
Field getField(String name) | 返回单个成员变量对象(只能拿public的) |
Field getDeclaredField(String name) | 返回单个成员变量对象,存在就能拿到 |
package com.jiangxian.reflect;
import java.lang.reflect.Field;
/**
* @author JiangXian~
* @version 1.0
*/
public class MyReflectDemo02 {
public static void main(String[] args) throws ClassNotFoundException {
Class clazz = Class.forName("com.jiangxian.reflect.Student");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
System.out.println(field.getName());
}
}
}
获取成员变量并修改值:
方法 | 说明 |
---|---|
void set(Object obj, Object value) | 赋值 |
Object get(Object obj) | 获取值 |
package com.jiangxian.reflect;
import java.lang.reflect.Field;
/**
* @author JiangXian~
* @version 1.0
*/
public class Field_ {
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
Student s = new Student("JiangXian", 21);
System.out.println(s);
Class clazz = Class.forName("com.jiangxian.reflect.Student");
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
field.set(s,"FengJiu");
System.out.println(s);
String n = (String) field.get(s);
System.out.println("name:" + n);
}
}
反射获取成员方法:
规则:
- get 表示获取;
- Declared 表示私有;
- 最后的 s 表示所有,复数形式;
- 若当前获取到的是私有的,那么我们必须要临时修改访问权限,否则无法使用。
方法名 | 说明 |
---|---|
Method[] getMethods() | 返回所有成员方法对象的数组(只能拿public的) |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,存在就能拿到 |
Method getMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象(只能拿public的) |
Method getDeclaredMethod(String name, Class<?>… parameterTypes) | 返回单个成员方法对象,存在就能拿到 |
package com.jiangxian.reflect;
import java.lang.reflect.Method;
/**
* @author JiangXian~
* @version 1.0
*/
public class MyReflectDemo03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class clazz = Class.forName("com.jiangxian.reflect.Student");
System.out.println("=========================");
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("=========================");
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(method);
}
System.out.println("=========================");
Method method = clazz.getMethod("getAge");
System.out.println(method);
}
}
获取成员方法并运行:
方法:
- Object invoke(Object obj, Object…args)
- 参数一:用 obj 对象调用该类方法;
- 参数二:调用方法的传递的参数(若没有就不写)。
- 返回值:方法的返回值(若没有就不写)
package com.jiangxian.reflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author JiangXian~
* @version 1.0
*/
public class Method_ {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class clazz = Class.forName("com.jiangxian.reflect.Student");
Method method = clazz.getMethod("getName");
Method method1 = clazz.getMethod("setName", String.class);
Student student = new Student("JiangXian", 21);
String name = (String) method.invoke(student);
System.out.println(name);
method1.invoke(student,"Fengjiu");
name = (String) method.invoke(student);
System.out.println(name);
}
}
etName");
Method method1 = clazz.getMethod(“setName”, String.class);
Student student = new Student("JiangXian", 21);
String name = (String) method.invoke(student);
System.out.println(name);
method1.invoke(student,"Fengjiu");
name = (String) method.invoke(student);
System.out.println(name);
}
}