反射允许对成员变量、成员方法和构造方法的信息进行编程访问。
因为反射需要对class文件进行操作,下面先介绍获取class对象的三种方式
获取class对象的三种方式:
1.Class.forName("全类名")
2.类名.class
3.对象.getClass
代码演示:
public class ClassDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
//1.Class.forName("全类名")
//全类名:包名+类名
//最为常用
Class clazz1 = Class.forName("com.han.reflection.Student");
//2.类名.class
//一般更多是当作参数进行传递
Class clazz2 = Student.class;
//3.对象.getClass
//当已经有了这个类的对象时,才可以使用
Student s = new Student();
Class clazz3 = s.getClass();
System.out.println(clazz1 == clazz2);
System.out.println(clazz3 == clazz2);
}
}
运行结果:
反射获取
1.构造方法
代码演示:
测试类:
public class ClassDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class clazz = Class.forName("com.han.reflection.Student");
//获取所有public的构造方法
Constructor[] cons1 = clazz.getConstructors();
for (Constructor constructor : cons1) {
System.out.println(constructor);
}
System.out.println("-----------------------------");
//获取所有的构造方法
Constructor[] cons2 = clazz.getDeclaredConstructors();
for (Constructor constructor : cons2) {
System.out.println(constructor);
}
System.out.println("-----------------------------");
//获取单个public修饰的构造方法(参数中要写对应参数类型的字节码文件)
Constructor con1 = clazz.getConstructor();
System.out.println(con1);
Constructor con2 = clazz.getConstructor(int.class);
System.out.println(con2);
System.out.println("-----------------------------");
//获取单个任意修饰符修饰的构造方法(参数中要写对应参数类型的字节码文件)
Constructor con3 = clazz.getDeclaredConstructor(String.class);
System.out.println(con3);
Constructor con4 = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(con4);
System.out.println("-----------------------------");
//获取构造方法的权限修饰符
int modifiers = con4.getModifiers();
System.out.println(modifiers);
System.out.println("-----------------------------");
//利用获取的构造方法创建对象
//创建有权限调用的
Student stu1 = (Student) con2.newInstance(21);
System.out.println(stu1);
System.out.println("-----------------------------");
//创建没有权限调用的
//硬调用
//暴力反射:临时取消权限检验
con4.setAccessible(true);
Student stu2 = (Student) con4.newInstance("han", 22);
System.out.println(stu2);
}
}
Student类:
public class Student {
private String name;
private int age;
public Student() {
}
public Student(int age) {
this.age = age;
}
protected Student(String name) {
this.name = name;
}
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 + "}";
}
}
运行结果:
2.成员变量
代码演示:
测试类:
public class ReflcetionDemo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//获取字节码文件
Class clazz = Class.forName("com.han.reflection.field.Student");
//获取所有的成员变量
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("------------------------------");
//获取单个成员变量
Field name = clazz.getDeclaredField("name");
System.out.println(name);
System.out.println("------------------------------");
//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
System.out.println("------------------------------");
//获取成员变量名字
String n = name.getName();
System.out.println(n);
System.out.println("------------------------------");
//获取成员变量数据类型
Class type = name.getType();
System.out.println(type);
System.out.println("------------------------------");
//获取成员变量记录的值
Student stu = new Student("han",21,"男");
//暴力反射
name.setAccessible(true);
String value = (String) name.get(stu);
System.out.println(value);
//修改成员变量记录的值
name.set(stu,"hanhan");
System.out.println(stu);
}
}
Student类:
public class Student {
private String name;
private int age;
public String gender;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
/**
* 获取
* @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 String getGender() {
return gender;
}
/**
* 设置
* @param gender
*/
public void setGender(String gender) {
this.gender = gender;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + ", gender = " + gender + "}";
}
}
运行结果:
3.成员方法
代码演示:
测试类:
public class ReflectionDemo1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//获取字节码文件对象
Class clazz = Class.forName("com.han.reflection.method.Student");
//获取所有的方法对象(包含父类中所有的公共方法)
Method[] methods = clazz.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("------------------");
//获取所有的方法对象(不能获取父类的,但是可以获取本类中私有的方法)
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("------------------");
//获取指定的单一方法
Method method = clazz.getDeclaredMethod("eat", String.class);
System.out.println(method);
System.out.println("------------------");
//获取方法的修饰符
int modifiers = method.getModifiers();
System.out.println(modifiers);
System.out.println("------------------");
//获取方法的名字
String name = method.getName();
System.out.println(name);
System.out.println("------------------");
//获取方法的形参
Parameter[] parameters = method.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
System.out.println("------------------");
//获取方法抛出的异常
Class[] exceptionTypes = method.getExceptionTypes();
for (Class exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
System.out.println("------------------");
//运行方法
//先创建对象
Student s = new Student();
method.setAccessible(true);
method.invoke(s, "包子");
}
}
Student类:
public class Student {
private String name;
private int age;
public void sleep() {
System.out.println("在睡觉");
}
private void eat(String something) throws IOException , ClassCastException {
System.out.println("在吃" + something);
}
private void eat(String something, int n) {
System.out.println("在吃" + something);
}
}
运行结果:
单词含义:
get:获取 | set:设置 |
Constructor:构造方法 | Parameter:参数 |
Field:成员变量 | Modifiers:修饰符 |
Method:方法 | Declared:私有的 |
反射的作用:
1.获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
2.结合配置文件,动态的创建对象并调用方法
练习题:
练习一:
定义一个方法,对于任何一个对象,都可以把对象所有的字段名和值,保存到文件中去
代码演示:
测试类:
public class Test1 {
public static void main(String[] args) throws IOException, IllegalAccessException {
//定义一个方法,对于任何一个对象,都可以把对象所有的字段名和值,保存到文件中去
Student s = new Student("han",21,"男",175.0);
Teacher t = new Teacher("zhang",36);
saveObject(s);
saveObject(t);
}
private static void saveObject(Object obj) throws IllegalAccessException, IOException {
Class clazz = obj.getClass();
BufferedWriter bw = new BufferedWriter(new FileWriter(
"C:\\Users\\Han\\IdeaProjects\\myreflection\\src\\com\\han\\reflection\\test\\test1\\a.txt",true));
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
Object o = field.get(obj);
bw.write(name + "=" + o);
bw.newLine();
}
bw.close();
}
}
Student类:
public class Student {
private String name;
private int age;
private String gender;
private double height;
public Student() {
}
public Student(String name, int age, String gender, double height) {
this.name = name;
this.age = age;
this.gender = gender;
this.height = height;
}
/**
* 获取
* @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 String getGender() {
return gender;
}
/**
* 设置
* @param gender
*/
public void setGender(String gender) {
this.gender = gender;
}
/**
* 获取
* @return height
*/
public double getHeight() {
return height;
}
/**
* 设置
* @param height
*/
public void setHeight(double height) {
this.height = height;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + ", gender = " + gender + ", height = " + height + "}";
}
}
Teacher类:
public class Teacher {
private String name;
private int age;
public Teacher() {
}
public Teacher(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 "Teacher{name = " + name + ", age = " + age + "}";
}
}
运行结果:
练习二:
通过将反射和配置文件结合,动态的创建对象,并调用方法
配置文件:
代码演示:
测试类:
public class Test {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//读取配置文件信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream(
"C:\\Users\\Han\\IdeaProjects\\myreflection\\src\\com\\han\\reflection\\test\\test2\\prop.properties");
prop.load(fis);
//{classname=com.han.reflection.test.test2.Student, methodname=study}
String className = (String) prop.get("className");
String methodName = (String) prop.get("methodName");
//获取字节码文件
Class clazz = Class.forName(className);
//获取构造方法
Constructor cons = clazz.getDeclaredConstructor();
Object o = cons.newInstance();
//调用方法
Method method = clazz.getMethod(methodName);
method.setAccessible(true);
method.invoke(o);
}
}
Student类:
public class Student {
private String name;
private int age;
public void study() {
System.out.println("学生在学习");
}
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 + "}";
}
}