反射的概述
反射机制
- 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意属性和方法;
- 这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。
总结下来
- 利用反射可以无视修饰符获取类里面所有的属性和方法
- 先获取配置文件中的信息,动态获取(如从配置文件中的读取)信息并创建对象和调用方法
获取 Class 对象
调用一个类中的方法(如上图所示)
- 创建这个类的对象
- 用对象调用方法
反射去调用一个类中的方法(如上图所示)
- 反射方式:创建对象
- 反射方式:调用方法
那么现在的问题就是如何获取这个 Class 对象
数据准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| public class Student { private String name; private int age;
public Student() { }
public Student(String name, int age) { this.name = name; this.age = age; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public void study(){ System.out.println("学生在学习"); }
@Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|
三种获取 Class 对象方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public class ReflectDemo1 { public static void main(String[] args) throws ClassNotFoundException { Class clazz = Class.forName("com.itheima.myreflect2.Student"); System.out.println(clazz);
Class clazz2 = Student.class; System.out.println(clazz2);
Student s = new Student(); Class clazz3 = s.getClass(); System.out.println(clazz3);
System.out.println(clazz == clazz2); System.out.println(clazz2 == clazz3); } }
|
反射获取 Class 类的对象
Class 类的对象包括:成员变量对象、构造器对象及成员方法对象
数据准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class Student { private String name; private int age;
private Student(String name) { System.out.println("name的值为:" + name); System.out.println("private...Student...有参构造方法"); }
public Student() { System.out.println("public...Student...无参构造方法"); }
public Student(String name, int age) { System.out.println("name的值为:" + name + "age的值为:" + age); System.out.println("public...Student...有参构造方法"); } }
|
获取 Constructor 对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| public class ReflectDemo1 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { }
private static void method4() throws ClassNotFoundException, NoSuchMethodException { Class clazz = Class.forName("com.itheima.myreflect3.Student"); Constructor constructor = clazz.getDeclaredConstructor(String.class); System.out.println(constructor); }
private static void method3() throws ClassNotFoundException, NoSuchMethodException { Class clazz = Class.forName("com.itheima.myreflect3.Student"); Constructor constructor1 = clazz.getConstructor(); System.out.println(constructor1); Constructor constructor2 = clazz.getConstructor(String.class, int.class); System.out.println(constructor2);
Constructor constructor3 = clazz.getConstructor(int.class); System.out.println(constructor3); }
private static void method2() throws ClassNotFoundException { Class clazz = Class.forName("com.itheima.myreflect3.Student"); Constructor[] constructors = clazz.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } }
private static void method1() throws ClassNotFoundException { Class clazz = Class.forName("com.itheima.myreflect3.Student"); Constructor[] constructors = clazz.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } } }
|
Constructor 创建对象
那么我们获取到的 Class 对象中的构造方法,不就是为了使用它来创建对象嘛,方法如下:
T newInstance(Object…initargs)
:根据指定的构造方法创建对象(T 表示返回值类型,此处为创建对来的对象)
setAccessible(boolean flag)
:设置为 true,表示取消访问检查(通过获取私有的构造方法来创建对象,如果用反射强行获取并使用,需要临时取消访问检查)
也就是说,如果构造方法是 public 的,直接使用 newInstance 即可创建对象;如果构造方法是 private 的,那么需要在创建对象之前临时取消访问检查,也就是 暴力反射
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| public class ReflectDemo2 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
} private static void method1() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor constructor = clazz.getConstructor(String.class, int.class);
Student student = (Student) constructor.newInstance("zhangsan", 23);
System.out.println(student); } private static void method2() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor constructor = clazz.getConstructor();
Student student = (Student) constructor.newInstance();
System.out.println(student); }
private static void method3() throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class clazz = Class.forName("com.itheima.myreflect3.Student");
Student student = (Student) clazz.newInstance();
System.out.println(student); }
private static void method4() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Class clazz = Class.forName("com.itheima.myreflect3.Student");
Constructor constructor = clazz.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("zhangsan");
System.out.println(student); }
}
|
反射获取成员变量
- 获取 Class 对象
- 获取 Field 对象
- 赋值或者取值
数据准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Student { public String name; public int age; public String gender; private int money = 300; @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", gender='" + gender + '\'' + ", money=" + money + '}'; } }
|
获取成员变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| public class ReflectDemo1 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { } private static void method1() throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field[] fields = clazz.getFields();
for (Field field : fields) { System.out.println(field); } }
private static void method2() throws ClassNotFoundException { Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) { System.out.println(field); } }
private static void method3() throws ClassNotFoundException, NoSuchFieldException { Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field field = clazz.getField("money");
System.out.println(field); }
private static void method4() throws ClassNotFoundException, NoSuchFieldException { Class clazz = Class.forName("com.itheima.myreflect4.Student");
Field field = clazz.getDeclaredField("money");
System.out.println(field); } }
|
Field 对象取值或赋值
既然获取到 Field 对象了,那么就赋值或取值吧
赋值:void set(Object obj, Object value)
,给指定对象的成员变量赋值
取值:Object get(Object obj)
,返回指定对象的 Field 值
为什么中间需要有一个 Object 类呢?比如遇到如下情形,set 方法怎么知道需要将值赋给谁呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| public class ReflectDemo2 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException { private static void method1() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException { Class clazz = Class.forName("com.itheima.myreflect4.Student"); Field field = clazz.getField("name"); Student student = (Student) clazz.newInstance(); field.set(student,"zhangsan"); System.out.println(student); } private static void method2() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException { Class clazz = Class.forName("com.itheima.myreflect4.Student"); Field field = clazz.getDeclaredField("money"); field.setAccessible(true); Student student = (Student) clazz.newInstance(); Object o = field.get(student); System.out.println(o); } }
|
反射获取成员方法
- 获取 Class 对象
- 获取 Method 对象
- 运行方法
Method[] getMethods()
:返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods()
:返回所有成员方法对象的数组,不包括继承的
- 返回单个公共成员方法对象
- 返回单个成员方法对象
数据准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class Student { private void show() { System.out.println("私有的show方法,无参无返回值"); } public void function1() { System.out.println("function1方法,无参无返回值"); } public void function2(String name) { System.out.println("function2方法,有参无返回值,参数为" + name); } public String function3() { System.out.println("function3方法,无参有返回值"); return "aaa"; } public String function4(String name) { System.out.println("function4方法,有参有返回值,参数为" + name); return "aaa"; } }
|
获取成员方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public class ReflectDemo1 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { }
private static void method1() throws ClassNotFoundException { Class clazz = Class.forName("com.itheima.myreflect5.Student"); Method[] methods = clazz.getMethods(); for (Method method : methods) { System.out.println(method); } }
private static void method2() throws ClassNotFoundException {
Class clazz = Class.forName("com.itheima.myreflect5.Student");
Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } }
private static void method3() throws ClassNotFoundException, NoSuchMethodException { Class clazz = Class.forName("com.itheima.myreflect5.Student"); Method method1 = clazz.getMethod("function1"); System.out.println(method1); }
private static void method4() throws ClassNotFoundException, NoSuchMethodException { Class clazz = Class.forName("com.itheima.myreflect5.Student"); Method method = clazz.getMethod("function2", String.class); System.out.println(method); }
private static void method5() throws ClassNotFoundException, NoSuchMethodException { Class clazz = Class.forName("com.itheima.myreflect5.Student"); Method method = clazz.getDeclaredMethod("show"); System.out.println(method); } }
|
运行成员方法
Object invoke(Object obj, Object… args)
:运行方法
- 参数 1:用 obj 对象调用该方法
- 参数 2:调用方法的传递的参数(如果没有就不写)
- 返回值:方法的返回值(如果没有就不写)
比如说,我们现在想通过反射来获取 Class 中的 function4 方法,并运行它
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class ReflectDemo2 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Class clazz = Class.forName("com.itheima.myreflect5.Student"); Method method = clazz.getMethod("function4", String.class); Student student = (Student) clazz.newInstance(); Object result = method.invoke(student, "zhangsan"); System.out.println(result); } }
|