一、反射
1.反射:反射允许对封装类的字段,方法和构造函数的信息进行编程访问
二、获取class对象的三种方式
①class.forName("全类名");---->源代码阶段
②类名.class------>加载阶段
③对象.getClass();------>运行阶段
代码演示:
Student类:
package a10myreflect;
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 + "}";
}
}
测试类:
package a10myreflect;
public class MyReflectDemo1 {
public static void main(String[] args) throws ClassNotFoundException {
//1.第一种方式
//最为常用的
Class clazz1 = Class.forName("a10myreflect.Student");
//打印
//System.out.println(clazz1);//class a10myreflect.Student
//第二种方式
//一般更多的是当做参数进行传递
//例如:synchronized ()
Class clazz2 = Student.class;
// System.out.println(clazz1==clazz2);//true
//第三种方式
//当我们已经有了这个类的对象时才可以使用
Student s=new Student();
Class clazz3 = s.getClass();
System.out.println(clazz1==clazz2);//true
System.out.println(clazz2==clazz3);//true
}
}
运行结果:
三、反射获取构造方法
代码演示:
Student1类:
package a10myreflect;
public class Student1 {
private String name;
private int age;
public Student1() {
}
public Student1(String name){
this.name=name;
}
protected Student1(int age){
this.age=age;
}
private Student1(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 "Student1{name = " + name + ", age = " + age + "}";
}
}
测试类:
package a10myreflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class MyReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.获取class字节码文件对象
Class clazz = Class.forName("a10myreflect.Student1");
//2.获取构造方法
/* Constructor[] cons = clazz.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
*/
/* Constructor[] cons2 = clazz.getDeclaredConstructors();
for (Constructor con : cons2) {
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);//2
Parameter[] parameters = con4.getParameters();//获取全部参数
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
*/
//临时取消权限的校验--->暴力反射
con4.setAccessible(true);
Student1 stu = (Student1) con4.newInstance("zhangsan", 23);//创建对象
System.out.println(stu);
}
}
运行结果:
四、反射获取成员变量
代码演示:
Student2类:
package a10myreflect;
public class Student2 {
private String name;
private int age;
public String gender;
public Student2() {
}
public Student2(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 "Student2{name = " + name + ", age = " + age + ", gender = " + gender + "}";
}
}
测试类:
package a10myreflect;
import java.lang.reflect.Field;
public class MyReflectDemo3 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//1.获取class字节码文件对象
Class clazz = Class.forName("a10myreflect.Student2");
//2.获取所有的成员变量
/* Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
*/
//获取单个的成员变量
Field gender = clazz.getField("gender");
System.out.println(gender);//public java.lang.String a10myreflect.Student2.gender
Field name = clazz.getDeclaredField("name");
System.out.println(name);//private java.lang.String a10myreflect.Student2.name
//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);//2
//获取成员变量名
String n = name.getName();
System.out.println(n);//name
//获取成员变量数据类型
Class<?> type = name.getType();
System.out.println(type);//class java.lang.String
//获取成员变量记录的值
Student2 s=new Student2("zhangsan",23,"男");
name.setAccessible(true);
String value = (String) name.get(s);
System.out.println(value);//zhangsan
//修改对象里面记录的值
name.set(s,"lisi");
System.out.println(s);//Student2{name = lisi, age = 23, gender = 男}
}
}
运行结果:
五、反射获取成员方法
代码演示:
Student3类:
package a10myreflect;
import java.io.IOException;
public class Student3 {
private String name;
private int age;
public Student3() {
}
public Student3(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 void sleep(){
System.out.println("睡觉");
}
private String eat(String something)throws IOException,NullPointerException,ClassCastException {
System.out.println("在吃"+something);
return "好吃";
}
public String toString() {
return "Student3{name = " + name + ", age = " + age + "}";
}
}
测试类:
package a10myreflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class MyReflectDemo4 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.获取class字节码文件对象
Class clazz = Class.forName("a10myreflect.Student3");
//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);//private void a10myreflect.Student3.eat(java.lang.String)
//获取方法的修饰符
int modifiers = m.getModifiers();
System.out.println(modifiers);//2
//获取方法的名字
String name = m.getName();
System.out.println(name);//eat
//获取方法的形参
Parameter[] parameters = m.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);//java.lang.String arg0
}
//获取方法的抛出异常
Class<?>[] exceptionTypes = m.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
//方法运行
Student3 s=new Student3();
//参数1 s:表式方法的调用者
//参数2:“火锅”:表示在调用方法的时候传递的实际参数
m.setAccessible(true);
String result =(String) m.invoke(s, "火锅");//在吃火锅
System.out.println(result);//好吃
}
}
运行结果:
五、反射的作用:
①获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
②结合配置文件,动态的创建对象并调用方法
练习1:保存信息
对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
Student类:
package a11myreflect;
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 + "}";
}
}
Teacher类:
package a11myreflect;
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 a11myreflect;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class MyReflectDemo {
public static void main(String[] args) throws IllegalAccessException, IOException {
Student s=new Student("小A",23,'女',167.5,"睡觉");
Teacher t=new Teacher("小B",10000);
saveObject(t);
}
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
//1.获取字节码文件的对象
Class<?> clazz = obj.getClass();
//创建IO流
BufferedWriter bw=new BufferedWriter(new FileWriter("Test\\a.txt"));
//2.获取所有的成员变量
Field[] fileds = clazz.getDeclaredFields();
for (Field field : fileds) {
field.setAccessible(true);
//获取成员变量的名字
String name = field.getName();
//获取成员变量的值
Object value = field.get(obj);
//写出数据
bw.write(name+"="+value);
bw.newLine();//换行
}
bw.close();
}
}
运行结果:
练习2:跟配置文件结合动态创建
反射可以跟配置文件结合的方式,动态的创建对象,并调用方法