JAVA--反射
JAVA--反射
什么是反射?
可以从类里面将该类的成员方法成员变量,构造方法的信息给拿出来
使用可以获取成员变量,构造方法,成员方法的所有信息.
学习反射应该学习如何获取和解剖
获取class对象的三种方式
-
在源代码阶段使用Class.forName("全类名");(最常用)
-
在加载阶段使用A.class(一般更多是当作参数传递)
-
在运行阶段使用对象.getClass();(已经有了这个类的对象才能使用)
代码演示
public class MyReflectDemo01 { public static void main(String[] args) throws ClassNotFoundException { //1.第一种方式 //全类名:包名+类名 Student Class clazz = Class.forName("Student"); //打印 System.out.println(clazz); //第二种方式 Class clazz2 = Student.class; //打印 System.out.println(clazz2); System.out.println(clazz == clazz2);//两个获取的是一个对象 //第三种方式 Student s = new Student(); Class clazz3 = s.getClass(); System.out.println(clazz3); //获取的字节码文件对象是一样的 System.out.println(clazz3 == clazz2); System.out.println(clazz2 == clazz); } }
下面是一个标准的Java类
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; } }
利用反射获取构造方法
在Java当中万物皆可对象,所以如图所示: Class有对象,构造方法有对象,成员变量和成员方法也有对象
- 返回所有public修饰的构造方法
- 返回所有的构造方法
- 返回单个的public修饰的构造方法
- 返回单个的构造方法
一个Student类
public class Student {
private String name;
private int age;
private Student(int age) {
this.age = age;
}
private Student(String name) {
this.name = name;
}
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;
}
}
反射的各种方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
public class MyReflectDemo02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//获取class字节码文件对象
Class clazz = Class.forName("Student");
//获取public构造方法
/*
Constructor[] cons =clazz.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
*/
//获取所有构造方法
// Constructor[] con1 =clazz.getDeclaredConstructors();
// for (Constructor con : con1) {
// System.out.println(con);
// }
//获取单个构造方法
// Constructor con1 = clazz.getDeclaredConstructor();
// System.out.println(con1);
// //向里面传递的是字节码文件
// Constructor con2 = clazz.getDeclaredConstructor(String.class);
// System.out.println(con2);
// Constructor con3 = clazz.getDeclaredConstructor(int.class);
// System.out.println(con3);
Constructor con4 = clazz.getDeclaredConstructor(String.class, int.class);
// System.out.println(con4);
// int modifiers = con4.getModifiers();//可以获取权限修饰符
// System.out.println(modifiers);
// Student stu = new Student();
// Parameter[] parameters = con4.getParameters();
// for (Parameter parameter : parameters) {
// System.out.println(parameter);
// }
}
}
使用反射创建对象
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class MyReflectDemo02 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取class字节码文件对象
Class clazz = Class.forName("Student");
Constructor con3 = clazz.getDeclaredConstructor(String.class);
//暴力反射:临时取消权限校验
con3.setAccessible(true);
Student stu = (Student) con3.newInstance("张三");//本身为private修饰
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;
}
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;
}
}
使用反射获取成员变量之后的各种操作
import java.lang.reflect.Field;
public class MyReflectDemo01 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//1.获取class字节码文件的对象
Class clazz = Class.forName("Student");
//2.获取成员变量
// Field[] fields = clazz.getFields();
//获取所有成员变量
// Field[] fields = clazz.getDeclaredFields();
// for (Field field : fields) {
// System.out.println(field);
// }
//获取单个public成员变量
// Field gender = clazz.getField("gender");
// System.out.println(gender);
// 获取单个成员变量
Field name = clazz.getDeclaredField("name");
System.out.println(name);
//获取权限修饰符(也是int类型整数)
int modifiers = name.getModifiers();
System.out.println(modifiers);
//获取变量名
String n = name.getName();
System.out.println(n);
//获取成员变量数据类型
Class<?> type = name.getType();
System.out.println(type);
//获取成员变量记录的值
Student s = new Student("zhangsan", 23, "男");
name.setAccessible(true);//临时取消访问权限
String value = (String) name.get(s);
System.out.println(value);
//修改对象里面的值
name.set(s, "lisi");
System.out.println(s);
}
}
反射获取成员方法
一个Student类
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;
}
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 sleep() {
System.out.println("睡觉");
}
private String eat(String something) throws IOException, NullPointerException {
System.out.println("在吃" + something);
return "奥里给";
}
private String eat(String something, int a) {
System.out.println("在吃" + something);
return "奥里给";
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
使用反射调用成员方法的各种操作
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class MyReflectDemo03 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.获取字节码文件对象
Class clazz = Class.forName("Student");
//2.获取里面所有的方法对象(包含父类所有的公共方法)
// Method[] methods = clazz.getMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
//获取里面所有的方法对象(不可获取父类的公共方法),但是可以获取本类中私有的方法
// Method[] methods = clazz.getDeclaredMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
//获取指定的单一方法
Method m = clazz.getDeclaredMethod("eat", String.class);
System.out.println(m);
//获取方法修饰符
int modifiers = m.getModifiers();
System.out.println(m);
//方法的名字
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);
}
//方法运行 invoke方法
Student s = new Student();
//参数1:表示方法的调用者
//参数2:表示在调用方法的时候传递的实际参数
m.setAccessible(true);
m.invoke(s, "汉堡");
//如果方法带返回值的话
Object result = m.invoke(s, "汉堡包");
System.out.println(result);
}
}
反射的作用
练习:保存信息
一个Student类和Teacher类
import java.io.IOException;
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender=" + gender +
", height=" + height +
", hobby='" + hobby + '\'' +
'}';
}
}
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;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", salary=" + salary +
'}';
}
}
然后通过反射和IO流将文件写到a.txt里面
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class MyReflectDemo01 {
public MyReflectDemo01() throws IOException {
}
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 {
//1.获取字节码文件的对象
Class clazz = obj.getClass();
//2.获取成员变量
Field[] fields = clazz.getDeclaredFields();
//把对象里面所有的成员变量名保存到本地文件当中
//创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("src\\a.txt"));
for (Field field : fields) {
field.setAccessible(true);
//获取成员变量名字
String name = field.getName();
//获取成员变量值
Object value = field.get(obj);
//写入文件
bw.write(name + "=" + value);
bw.newLine();;
}
bw.close();
}
}
练习:跟配置文件结合动态创建
一个Student类
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;
}
public void study() {
System.out.println("学生在学习!");
}
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
一个测试类
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class MyReflectDemo01 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.读取配置文件中的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("src\\prop.properties");
prop.load(fis);
fis.close();
//带你prop信息
System.out.println(prop);
//2.获取全类名和方法名,这时候已经获取到全类名和方法名
String classname = (String) prop.get("classname");
String methodName = (String) prop.get("method");
System.out.println(classname);
System.out.println(methodName);
//3.利用反射创建对象并运行方法
Class clazz = Class.forName(classname);
//获取构造方法
Constructor con = clazz.getDeclaredConstructor();
//利用构造方法创建对象
Object o = con.newInstance();
System.out.println(o);
//利用反射获取成员方法
Method method = clazz.getDeclaredMethod(methodName);
method.setAccessible(true);//临时打开权限
method.invoke(o);//调用方法
}
}
配置文件
classname=Teacher
method=teach
就可以实现上面的练习了