反射
概念
专业的解释:
- 反射允许对成员变量、成员方法、构造方法的信息进行编程访问
- 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
- 对于任意一个对象,都能够调用它的任意属性和方法;
- 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
通俗的理解:
- 利用反射创建的对象可以无视修饰符调用类里面的内容
- 可以跟配置文件结合起来使用,把要创建的对象信息和方法写在配置文件中。读取到什么类,就创建什么类的对象读取到什么方法,就调用什么方法此时当需求变更的时候不需要修改代码,只要修改配置文件即可。

获取class对象的三种方式
- Class.forName(“全类名”)
在源代码阶段使用
- 类名.class
在加载阶段使用
- 对象.getClass();
运行阶段使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
Class clazz1 = Class.forName("com.itheima.reflectdemo.Student");
Class clazz2 = Student.class;
System.out.println(clazz1 == clazz2);
Student s = new Student(); Class clazz3 = s.getClass(); System.out.println(clazz1 == clazz2); System.out.println(clazz2 == clazz3);
|
获取构造方法
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
| 方法名 |
说明 |
| Constructor<?>[] getConstructors() |
获得所有的构造(只能public修饰) |
| Constructor<?>[] getDeclaredConstructors() |
获得所有的构造(包含private修饰) |
| Constructor getConstructor(Class<?>… parameterTypes) |
获取指定构造(只能public修饰) |
| Constructor getDeclaredConstructor(Class<?>… parameterTypes) |
获取指定构造(包含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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| public class Student { private String name;
private int age;
public String gender;
public String address;
public Student() { }
public Student(String name, int age, String address) { this.name = name; this.age = age; this.address = address; }
public Student(String name, int age, String gender, String address) { this.name = name; this.age = age; this.gender = gender; this.address = address; }
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 String getGender() { return gender; }
public void setGender(String gender) { this.gender = gender; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String toString() { return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}"; } }
|
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
| public class ReflectDemo2 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { Class clazz = Class.forName("com.itheima.reflectdemo.Student");
Constructor[] constructors1 = clazz.getConstructors(); for (Constructor constructor : constructors1) { System.out.println(constructor); }
System.out.println("=======================");
Constructor[] constructors2 = clazz.getDeclaredConstructors();
for (Constructor constructor : constructors2) { System.out.println(constructor); } System.out.println("=======================");
Constructor con1 = clazz.getConstructor(); System.out.println(con1);
Constructor con2 = clazz.getConstructor(String.class,int.class); System.out.println(con2);
System.out.println("======================="); Constructor con3 = clazz.getDeclaredConstructor(); System.out.println(con3);
Constructor con4 = clazz.getDeclaredConstructor(String.class); System.out.println(con4); } }
|
获取构造方法并创建对象
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 Student { private String name;
private int age;
public Student() {
}
public Student(String name) { this.name = name; }
private 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 String toString() { return "Student{name = " + name + ", age = " + age + "}"; } }
|
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
|
Class clazz = Class.forName("com.itheima.a02reflectdemo1.Student");
Constructor con = clazz.getConstructor();
Student stu = (Student) con.newInstance(); System.out.println(stu);
System.out.println("=============================================");
Class clazz = Class.forName("com.itheima.a02reflectdemo1.Student");
Constructor con = clazz.getDeclaredConstructor(String.class, int.class);
con.setAccessible(true);
Student stu = (Student) con.newInstance("zhangsan", 23); System.out.println(stu);
|
获取成员变量
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
方法名:
| 方法名 |
说明 |
| Field[] getFields() |
返回所有成员变量对象的数组(只能拿public的) |
| Field[] getDeclaredFields() |
返回所有成员变量对象的数组,存在就能拿到 |
| Field getField(String name) |
返回单个成员变量对象(只能拿public的) |
| Field getDeclaredField(String name) |
返回单个成员变量对象,存在就能拿到 |
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
| public class ReflectDemo4 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
Class clazz = Class.forName("com.itheima.reflectdemo.Student");
Field[] fields1 = clazz.getFields(); for (Field field : fields1) { System.out.println(field); }
System.out.println("===============================");
Field[] fields2 = clazz.getDeclaredFields(); for (Field field : fields2) { System.out.println(field); }
System.out.println("===============================");
Field field4 = clazz.getField("gender"); System.out.println(field4);
System.out.println("==============================="); Field field5 = clazz.getDeclaredField("name"); System.out.println(field5);
} }
|
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
| public class Student { private String name;
private int age;
public String gender;
public String address;
public Student() { }
public Student(String name, int age, String address) { this.name = name; this.age = age; this.address = address; }
public Student(String name, int age, String gender, String address) { this.name = name; this.age = age; this.gender = gender; this.address = address; }
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 String getGender() { return gender; }
public void setGender(String gender) { this.gender = gender; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String toString() { return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}"; } }
|
获取成员变量并获取和修改值
| 方法 |
说明 |
| void set(Object obj, Object value) |
赋值 |
| Object get(Object obj) |
获取值 |
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
| public class ReflectDemo5 { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { Student s = new Student("zhangsan",23,"广州"); Student ss = new Student("lisi",24,"北京");
Class clazz = Class.forName("com.itheima.reflectdemo.Student");
Field field = clazz.getDeclaredField("name"); field.setAccessible(true);
field.set(s,"wangwu");
String result = (String)field.get(s);
System.out.println(result);
System.out.println(s); System.out.println(ss);
} }
|
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| public class Student { private String name; private int age; public String gender; public String address;
public Student() { }
public Student(String name, int age, String address) { this.name = name; this.age = age; this.address = address; }
public Student(String name, int age, String gender, String address) { this.name = name; this.age = age; this.gender = gender; this.address = address; }
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 String getGender() { return gender; }
public void setGender(String gender) { this.gender = gender; }
public String getAddress() { return address; }
public void setAddress(String address) { this.address = address; }
public String toString() { return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", address = " + address + "}"; } }
|
获取成员方法
规则:
get表示获取
Declared表示私有
最后的s表示所有,复数形式
如果当前获取到的是私有的,必须要临时修改访问权限,否则无法使用
| 方法名 |
说明 |
| Method[] getMethods() |
返回所有成员方法对象的数组(只能拿public的) |
| Method[] getDeclaredMethods() |
返回所有成员方法对象的数组,存在就能拿到 |
| Method getMethod(String name, Class<?>… parameterTypes) |
返回单个成员方法对象(只能拿public的) |
| Method getDeclaredMethod(String name, Class<?>… parameterTypes) |
返回单个成员方法对象,存在就能拿到 |
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
| public class ReflectDemo6 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { Class<?> clazz = Class.forName("com.itheima.reflectdemo.Student");
Method[] methods1 = clazz.getMethods(); for (Method method : methods1) { System.out.println(method); }
System.out.println("==========================="); Method[] methods2 = clazz.getDeclaredMethods(); for (Method method : methods2) { System.out.println(method); }
System.out.println("==========================="); Method method3 = clazz.getMethod("sleep"); System.out.println(method3);
Method method4 = clazz.getMethod("eat",String.class); System.out.println(method4);
Method method5 = clazz.getDeclaredMethod("playGame"); System.out.println(method5); } }
|
获取成员方法并运行
方法
Object invoke(Object obj, Object… args) :运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class ReflectDemo6 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class clazz = Class.forName("com.itheima.a02reflectdemo1.Student"); Student s = new Student(); Method eatMethod = clazz.getMethod("eat",String.class); String result = (String) eatMethod.invoke(s, "重庆小面"); System.out.println(result);
} }
|
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 67 68 69
| public class Student { private String name; private int age; public String gender; public String address;
public Student() {
}
public Student(String name) { this.name = name; }
private 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 String toString() { return "Student{name = " + name + ", age = " + age + "}"; }
private void study(){ System.out.println("学生在学习"); }
private void sleep(){ System.out.println("学生在睡觉"); }
public String eat(String something){ System.out.println("学生在吃" + something); return "学生已经吃完了,非常happy"; } }
|
练习
泛型擦除
集合中的泛型只在java文件中存在,当编译成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
| import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList;
public class ReflectDemo8 { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { ArrayList<Integer> list = new ArrayList<>(); list.add(123);
Class clazz = list.getClass();
Method method = clazz.getMethod("add", Object.class);
method.invoke(list,"aaa");
System.out.println(list); } }
|
修改字符串的内容
字符串,在底层是一个byte类型的字节数组,名字叫做value
1
| private final byte[] value;
|
真正不能被修改的原因:final和private
final修饰value表示value记录的地址值不能修改。
private修饰value而且没有对外提供getvalue和setvalue的方法。所以,在外界不能获取或修改value记录的地址值。
如果要强行修改可以用反射:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| String s = "abc"; String ss = "abc";
Class clazz = s.getClass();
Field field = clazz.getDeclaredField("value");
field.setAccessible(true);
byte[] bytes = (byte[]) field.get(s); bytes[0] = 100;
System.out.println(s); System.out.println(ss);
|
反射和配置文件结合动态获取(重点)
需求: 利用反射根据文件中的不同类名和方法名,创建不同的对象并调用方法。
分析:
①通过Properties加载配置文件
②得到类名和方法名
③通过类名反射得到Class对象
④通过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
| public class ReflectDemo9 { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Properties prop = new Properties(); FileInputStream fis = new FileInputStream("day14-code\\prop.properties"); prop.load(fis); fis.close(); System.out.println(prop);
String classname = prop.get("classname") + ""; String methodname = prop.get("methodname") + "";
Class clazz = Class.forName(classname);
Constructor con = clazz.getDeclaredConstructor(); con.setAccessible(true); Object o = con.newInstance(); System.out.println(o);
Method method = clazz.getDeclaredMethod(methodname); method.setAccessible(true);
method.invoke(o);
} }
|
利用反射保存对象中的信息(重点)
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
| public class MyReflectDemo { public static void main(String[] args) throws IllegalAccessException, IOException {
Student s = new Student("小A",23,'女',167.5,"睡觉"); Teacher t = new Teacher("播妞",10000); saveObject(s); }
public static void saveObject(Object obj) throws IllegalAccessException, IOException { Class clazz = obj.getClass(); BufferedWriter bw = new BufferedWriter(new FileWriter("myreflect\\a.txt")); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); String name = field.getName(); Object value = field.get(obj); bw.write(name + "=" + value); bw.newLine(); }
bw.close();
} }
|
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 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| public class Student { private String name; private int age; private char gender; private double height; private String hobby;
public Student() { }
public Student(String name, int age, char gender, double height, String hobby) { this.name = name; this.age = age; this.gender = gender; this.height = height; this.hobby = hobby; }
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 char getGender() { return gender; }
public void setGender(char gender) { this.gender = gender; }
public double getHeight() { return height; }
public void setHeight(double height) { this.height = height; }
public String getHobby() { return hobby; }
public void setHobby(String hobby) { this.hobby = hobby; }
public String toString() { return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", height = " + height + ", hobby = " + hobby + "}"; } }
|
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
| public class Teacher { private String name; private double salary;
public Teacher() { }
public Teacher(String name, double salary) { this.name = name; this.salary = salary; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public double getSalary() { return salary; }
public void setSalary(double salary) { this.salary = salary; }
public String toString() { return "Teacher{name = " + name + ", salary = " + salary + "}"; } }
|