Java反射
什么是反射?
反射允许对成员变量,成员方法和构造方法的信息进行编程访问
但是我们不是直接从 .java 文件里面获取的,而是先获取编译后字节码文件 .class,
再从中获取成员变量、构造方法、成员方法

获取 class 对象的三种方式
- Class.forName("全类名");// 源代码阶段
- 类名.class// 加载阶段
- 对象.getClass();// 运行阶段

package com.faxont.reflect1;
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
/*
获取 class 对象的三种方式:
1. Class.forName("全类名");
2. 类名.class
3. 对象.getClass();
*/
// 1. 第一种方式
// 全类名:包名 + 类名 com.faxont.reflect1.Student
// 最为常用的
// 只能写<?>
Class<?> clazz1 = Class.forName("com.faxont.reflect1.Student");
// 2. 第二种方式
// 一般更多的是当作参数进行传递
// 可以写<?>,也可以写<T>
Class<Student> clazz2 = Student.class;
// 例如:synchronized (Student.class){}
// synchronized (Student.class){
//
// }
// 3. 第三种方式
// 当我们已经有了这个类的对象时,才可以使用
// 只能写<?>
Student student = new Student();
Class<?> clazz3 = student.getClass();
System.out.println(clazz1 == clazz2);
System.out.println(clazz1 == clazz3);
System.out.println(clazz2 == clazz3);
}
}
package com.faxont.reflect1;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
利用反射获取构造方法
Class 类中用于获取构造方法的方法
Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
Constructor
Constructor
Constructor 类中用于创建对象的方法
T newInstance(Object... initargs):根据指定的构造方法创建对象
setAccessible(boolean flag):设置为 true,表示取消访问检查
package com.faxont.reflect2;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
/*
Class 类中用于获取构造方法的方法
Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes):返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象
Constructor 类中用于创建对象的方法
T newInstance(Object... initargs):根据指定的构造方法创建对象
setAccessible(boolean flag):设置为 true,表示取消访问检查
*/
// 1. 获取 Class 字节码文件的对象
// Class<?> clazz = Class.forName("com.faxont.reflect2.Student");
Class<Student> clazz = Student.class;
// 2. 获取所有公共构造方法对象(public)
// Constructor<?>[] cons = clazz.getConstructors();
// for (Constructor<?> con : cons) {
// System.out.println(con);
// }
// 3. 获取所有构造方法对象
// Constructor<?>[] cons = clazz.getDeclaredConstructors();
// for (Constructor<?> con : cons) {
// System.out.println(con);
// }
// Constructor<Student> con1 = clazz.getConstructor();
// System.out.println(con1);
// Constructor<Student> con2 = clazz.getDeclaredConstructor(String.class);
// System.out.println(con2);
// Constructor<Student> con3 = clazz.getDeclaredConstructor(int.class);
// System.out.println(con3);
// System.out.println(con4);
Constructor<Student> con4 = clazz.getDeclaredConstructor(String.class, int.class);
// int modifiers = con4.getModifiers();// 获取修饰符
// System.out.println(modifiers);
//
// Parameter[] parameters = con4.getParameters();// 获取参数
// for (Parameter parameter : parameters) {
// System.out.println(parameter);
// }
// 表示临时取消权限的校验(暴力反射)
con4.setAccessible(true);
Student student = con4.newInstance("张三", 18);
System.out.println(student);
}
}
package com.faxont.reflect2;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name) {
this.name = name;
}
protected Student(int age){
this.age = age;
}
private Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
利用反射获取成员变量
Class 类中用于获取成员变量的方法
Field[] getFields():返回所有公共成员变量对象的数组
Field[] getDeclaredFields():返回所有成员变量对象的数组
Field getField(String name):返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象
Field 类中用于创建对象的方法
void set(Object obj, Object value):赋值
Object get(Object obj):获取值
package com.faxont.reflect3;
import java.lang.reflect.Field;
public class ReflectDemo {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
/*
Class 类中用于获取成员变量的方法
Field[] getFields():返回所有公共成员变量对象的数组
Field[] getDeclaredFields():返回所有成员变量对象的数组
Field getField(String name):返回单个公共成员变量对象
Field getDeclaredField(String name):返回单个成员变量对象
Field 类中用于创建对象的方法
void set(Object obj, Object value):赋值
Object get(Object obj):获取值
*/
// 1. 获取 Class 字节码文件的对象
Class<?> clazz = Class.forName("com.faxont.reflect3.Student");
// 2. 获取所有公共成员变量对象(public)
// Field[] fields1 = clazz.getFields();
// for (Field field : fields1) {
// System.out.println(field);
// }
// 3. 获取所有成员变量对象
// Field[] fields2 = clazz.getDeclaredFields();
// for (Field field : fields2) {
// System.out.println(field);
// }
Field field1 = clazz.getDeclaredField("name");
// System.out.println(field1);
Field field2 = clazz.getDeclaredField("age");
// System.out.println(field2);
Field field3 = clazz.getField("sex");
// System.out.println(field3);
int modifiers = field1.getModifiers();
System.out.println(modifiers);
// 获取成员变量的名字
String name = field1.getName();
System.out.println(name);
// 获取成员变量的数据类型
Class<?> type = field1.getType();
System.out.println(type);
// 获取成员变量记录的值
Student s = new Student("zhangsan", 18, "男");
field1.setAccessible(true);
String value = (String) field1.get(s);
System.out.println(value);
// 修改成员变量的值
field1.set(s, "lisi");
System.out.println(s);
}
}
package com.faxont.reflect;
public class Student {
private String name;
private int age;
public String sex;
public Student() {
}
public Student(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取
* @return sex
*/
public String getSex() {
return sex;
}
/**
* 设置
* @param sex
*/
public void setSex(String sex) {
this.sex = sex;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + ", sex = " + sex + "}";
}
}
利用反射获取成员方法
Class 类中用于获取成员方法的方法
Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes):返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象
Method 类中用于创建对象的方法
Object invoke(Object obj, Object... args):运行方法
参数一:用 obj 对象调用该方法
参数二:在调用方法中传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
package com.faxont.reflect4;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
/*
Class 类中用于获取成员方法的方法
Method[] getMethods():返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>... parameterTypes):返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象
Method 类中用于创建对象的方法
Object invoke(Object obj, Object... args):运行方法
参数一:用 obj 对象调用该方法
参数二:在调用方法中传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
获取方法的修饰符
获取方法的名字
获取方法的形参
获取方法的抛出的异常
*/
// 1. 获取 Class 字节码文件的对象
Class<?> clazz = Class.forName("com.faxont.reflect4.Student");
// 2. 获取所有公共成员方法对象(public)(包含父类中的所有公共方法)
// Method[] methods1 = clazz.getMethods();
// for (Method method : methods1) {
// System.out.println(method);
// }
// 3. 获取所有成员方法对象(不包含父类中的方法,但是可以获取本类中私有的方法)
// Method[] methods2 = clazz.getDeclaredMethods();
// for (Method method : methods2) {
// System.out.println(method);
// }
// 获取指定的单一方法
Method m = clazz.getDeclaredMethod("eat", String.class, int.class);
System.out.println(m);
// 获取方法的修饰符
int modifiers = m.getModifiers();
System.out.println(modifiers);
// 获取方法名字
String name = m.getName();
System.out.println(name);
// 获取方法的形参
Parameter[] parameters = m.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
// 获取方法的抛出的异常
Class<?>[] exceptionTypes = m.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
/*
Method 类中用于创建对象的方法
Object invoke(Object obj, Object... args):运行方法
参数一:用 obj 对象调用该方法
参数二:在调用方法中传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
*/
// 方法运行
Student s = new Student();
m.setAccessible(true);
// 获取方法的返回值
String eat = (String) m.invoke(s, "憨包", 2);
System.out.println(eat);
}
}
package com.faxont.reflect4;
import java.io.IOException;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
public void sleep(){
System.out.println("zzz");
}
private void eat(String food) {
System.out.println("在吃" + food);
}
private String eat(String food, int count) throws IOException, NullPointerException, ClassCastException {
System.out.println("吃了" + count + "个" + food);
return "吃饱了";
}
}
反射的作用
- 获取一个类里面所有的信息,获取到了之后,再执行其它的业务逻辑
- 结合配置文件,动态地创建对象并调用方法
练习:保存信息
对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去

package com.faxont.com.practice1;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) {
/*
对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
*/
Student s = new Student("小A", 23, '女', 167.5, "睡觉");
Teacher t = new Teacher("播妞", 10000);
saveObject(s, "io\\student.txt");
saveObject(t, "io\\teacher.txt");
}
private static void saveObject(Object obj, String fileName){
Class clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
try(BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))){
for (Field field : fields) {
field.setAccessible(true);
writer.write(field.getName() + "=" + field.get(obj));
writer.newLine();
}
}catch (IOException | IllegalAccessException e){
e.printStackTrace();
}
}
}
package com.faxont.com.practice1;
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;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
/**
* 获取
* @return gender
*/
public char getGender() {
return gender;
}
/**
* 设置
* @param gender
*/
public void setGender(char gender) {
this.gender = gender;
}
/**
* 获取
* @return height
*/
public double getHeight() {
return height;
}
/**
* 设置
* @param height
*/
public void setHeight(double height) {
this.height = height;
}
/**
* 获取
* @return hobby
*/
public String getHobby() {
return hobby;
}
/**
* 设置
* @param hobby
*/
public void setHobby(String hobby) {
this.hobby = hobby;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", height = " + height + ", hobby = " + hobby + "}";
}
}
package com.faxont.com.practice1;
public class Teacher {
private String name;
private double salary;
public Teacher() {
}
public Teacher(String name, double salary) {
this.name = name;
this.salary = salary;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return salary
*/
public double getSalary() {
return salary;
}
/**
* 设置
* @param salary
*/
public void setSalary(double salary) {
this.salary = salary;
}
public String toString() {
return "Teacher{name = " + name + ", salary = " + salary + "}";
}
}
练习:跟配置文件结合动态创建
反射可以以跟配置文件结合的方式,动态地创建对象,并调用方法
package com.faxont.reflect5;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
public class ReflectDemo {
public static void main(String[] args) {
/*
反射可以以跟配置文件结合的方式,动态地创建对象,并调用方法
*/
// 1. 读取配置文件中的信息
Properties prop = new Properties();
try (FileInputStream fis = new FileInputStream("reflect\\prop.properties")){
prop.load(fis);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(prop);
// 2. 获取全类名和方法名
String className = prop.getProperty("classname");
String methodName = prop.getProperty("method");
System.out.println(className);
System.out.println(methodName);
// 3. 利用反射创建对象并运行方法
Class clazz = null;
try {
clazz = Class.forName(className);
Constructor con = clazz.getDeclaredConstructor();
Object o = con.newInstance();
System.out.println(o);
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
package com.faxont.reflect5;
public class Teacher {
private String name;
private double salary;
public Teacher() {
}
public Teacher(String name, double salary) {
this.name = name;
this.salary = salary;
}
public void teach(){
System.out.println("老师在教书!");
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return salary
*/
public double getSalary() {
return salary;
}
/**
* 设置
* @param salary
*/
public void setSalary(double salary) {
this.salary = salary;
}
public String toString() {
return "Teacher{name = " + name + ", salary = " + salary + "}";
}
}
package com.faxont.reflect5;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void study(){
System.out.println("学生在学习!");
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
classname=com.faxont.reflect5.Student
method=study

浙公网安备 33010602011771号