1.概述
什么是反射?:反射允许对封装类的字段,方法和构造函数的信息进行编程访问。
我们知道在idea里面编写Java代码的时候,编辑器会给我们提供一些编程的提示,这些其实就是底层用反射实现的。
2.获取class对象的三种方式
- Class.forName("全类名"); ---源代码阶段
- 类名.class; ---加载阶段
- 对象.getClass(); --运行阶段
- 样例代码:
Student类:
package com.qcby.MyReflect;
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试类:
package com.qcby.MyReflect;
public class MyReflectTest {
public static void main(String[] args) throws ClassNotFoundException {
method1();
method2();
method3();
}
/**
* 反射的第一种方式
* 最常用
*/
public static void method1() throws ClassNotFoundException {
System.out.println("第一种方式:");
//全类名: 包名+类名
Class clazz= Class.forName("com.qcby.MyReflect.Student");
System.out.println("反射的类:"+clazz);
}
/**
* 反射的第二种方式
* 一般更多的是当做参数来传递
*/
public static void method2(){
System.out.println("第二种方式:");
Class clazz= Student.class;
System.out.println("反射的类:"+clazz);
}
/**
* 反射的第三种方式
* 当已经有了一个类的实例的时候,使用方式三
*/
public static void method3(){
System.out.println("第三种方式:");
Student student=new Student();
Class clazz= student.getClass();
System.out.println("反射的类:"+clazz);
}
}
3.反射获取构造方法
代码示例:
package com.qcby.MyReflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Parameter;
public class MyConstructorReflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//获取class字节码文件对象
Class clazz=Class.forName("com.qcby.MyReflect.Student");
//获取所有公有构造方法
System.out.println("获取所有公有构造方法");
Constructor[] cons=clazz.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
System.out.println("获取所有构造方法");
Constructor[] cons2=clazz.getDeclaredConstructors();
for (Constructor con : cons2) {
System.out.println(con);
}
System.out.println("----------");
//通过无参数来获取无参构造函数
Constructor con3=clazz.getDeclaredConstructor();
System.out.println(con3);
System.out.println("----------");
//获取参数为String类型的构造函数,如果有多个参数,可以传递多个class对象
Constructor con4=clazz.getDeclaredConstructor(String.class);
System.out.println(con4);
System.out.println("----------");
Constructor con5=clazz.getDeclaredConstructor(String.class,int.class);
System.out.println(con5);
System.out.println("----------");
//权限修饰符用整数来代表
//public ---> 1
//private ---> 2
System.out.println("获取权限修饰符:");
int modifiers=con5.getModifiers();
System.out.println(modifiers);
System.out.println("----------");
System.out.println("获取参数:");
Parameter[] parameters=con5.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//利用构造方法创建对象实例
System.out.println("----------");
System.out.println("创建对象示例:");
con5.setAccessible(true);//设置该构造方法可得,即使是私有方法也可以执行,如果没有,就只能执行公有方法
Student student= (Student) con5.newInstance("张三", 12);
System.out.println(student);
}
}
4.反射获取成员变量
代码示例:
package com.qcby.MyReflect;
import java.lang.reflect.Field;
public class MyClassItemReflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
System.out.println("获取公共成员变量:");
//1.获取class字节码文件的对象
Class Clazz = Class.forName("com.qcby.MyReflect.Student");
//2.获取成员变量(所有公共属性的)
Field[] fields= Clazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("--------------");
System.out.println("获取所有成员变量:");
Field[] fields2= Clazz.getDeclaredFields();
for (Field field : fields2) {
System.out.println(field);
}
System.out.println("--------------");
System.out.println("获取单个公共属性的成员变量:");
Field field=Clazz.getField("gender");
System.out.println(field);
System.out.println("--------------");
System.out.println("获取单个任意属性的成员变量:");
Field field2=Clazz.getDeclaredField("age");
System.out.println(field2);
System.out.println("--------------");
System.out.println("获取成员变量的权限修饰符:");
int modifiers=field2.getModifiers();
System.out.println(modifiers);
System.out.println("--------------");
System.out.println("获取成员变量名和类型:");
String age = field2.getName();
Class type = field2.getType();
System.out.println(age+" "+type);
System.out.println("--------------");
System.out.println("获取成员变量所记录的值:");
Student student=new Student("张三",18,"男");
field2.setAccessible(true);//因为age成员变量是私有属性的
Object o = field2.get(student);
System.out.println(o);
System.out.println("--------------");
System.out.println("修改成员变量所记录的值:");
field2.set(student,20);
System.out.println(student);
}
}
Student类:
package com.qcby.MyReflect;
public class Student {
private String name;
private int age;
public String gender;
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
5.反射获取成员方法
代码示例:
package com.qcby.MyReflect;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class MyItemMethodReflect {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.获取class字节码文件对象
Class Clazz = Class.forName("com.qcby.MyReflect.Student");
System.out.println("获取类中所有公有的方法对象:");
Method[] methods = Clazz.getMethods();//包含父类中所有的公共方法
for (Method method : methods) {
System.out.println(method);
}
System.out.println("--------");
System.out.println("获取类中所有的方法对象:");
Method[] declaredMethods = Clazz.getDeclaredMethods();//不包含父类中的方法
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("--------");
System.out.println("获取类中某一个方法对象:");
Method eat = Clazz.getMethod("eat", String.class);//方法名+参数类型,防止重载函数
System.out.println(eat);
System.out.println("--------");
System.out.println("获取类中某一个任意属性的方法对象:");
Method eat2 = Clazz.getDeclaredMethod("eat", String.class);//方法名+参数类型,防止重载函数
System.out.println(eat2);
System.out.println("--------");
System.out.println("获取方法对象的权限修饰符:");
int modifiers = eat.getModifiers();
System.out.println(modifiers);
System.out.println("--------");
System.out.println("获取方法对象的名字:");
String name = eat.getName();
System.out.println(name);
System.out.println("--------");
System.out.println("获取方法对象的参数:");
Parameter[] parameters = eat.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
System.out.println("--------");
System.out.println("获取方法对象抛出的异常:");
Class[] exceptionTypes = eat.getExceptionTypes();
for (Class exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
System.out.println("--------");
System.out.println("运行方法:");
Student student=new Student("张三",15,"男");
eat.setAccessible(true);
//参数一:表示方法的调用者
//方法二:表示该方法的参数
eat.invoke(student,"麻辣烫");
}
}
Student类:
package com.qcby.MyReflect;
public class Student {
private String name;
private int age;
private String gender;
public Student() {
}
public Student(String name) {
this.name = name;
}
public Student(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
public void sleep(){
System.out.println("睡觉");
}
public void eat(String something) throws IllegalArgumentException,NoSuchMethodException,NoSuchFieldException{
System.out.println("在吃"+something);
}
}
6.总和案例一 --- 保存对象任意数据
对于任意一个对象,都可以把对象所有的字段名和值,保存在文件中去。
代码:
package com.qcby.MyReflect.Practice;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class MyTest {
public static void main(String[] args) throws IllegalAccessException, IOException {
Student student=new Student("小A",23,'女',167.5,"睡觉");
Teacher teacher=new Teacher("老王",10000);
saveObject(student);
}
//把对象里面所有的成员变量和值保存在本地文件中
public static void saveObject(Object obj) throws IllegalAccessException, IOException {
//1.获取字节码文件的对象
Class clazz = obj.getClass();
//创建IO流
BufferedWriter bufferedWriter=new BufferedWriter(new FileWriter("D:\\JavaProject\\qcby-l\\out.txt"));
//2.获取所有的成员变量
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
declaredField.setAccessible(true);//临时取消访问权限,即取消私有属性
//获取成员变量的名字
String name = declaredField.getName();
//获取成员变量的值
Object value = declaredField.get(obj);
System.out.println(name+"="+value);
bufferedWriter.write(name+"="+value);//写入
bufferedWriter.newLine(); //换行
}
bufferedWriter.close();
}
}
Student类:
package com.qcby.MyReflect.Practice;
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 + '\'' +
'}';
}
}
Teacher类:
package com.qcby.MyReflect.Practice;
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 +
'}';
}
}
7.总和案例二 --- 利用反射动态的创建对象和运行方法
反射可以跟配置文件结合的方式,动态的创建对象,并调用方法。
package com.qcby.MyReflect.Practice2;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class MyTest {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//1.读取配置文件中的信息
Properties prop=new Properties();
FileInputStream fileInputStream=new FileInputStream("prop.properties");
prop.load(fileInputStream);
fileInputStream.close();
System.out.println(prop);
//2.获取全类名和方法名
String className = (String) prop.get("classname");
String methodName=(String) prop.get("method");
System.out.println(className+" "+methodName);
//3.利用反射创建对象并运行方法
Class clazz = Class.forName(className);
//获取构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor();
Object obj = declaredConstructor.newInstance();
System.out.println(obj);
//获取成员方法并运行
Method declaredMethod = clazz.getDeclaredMethod(methodName);
declaredMethod.setAccessible(true);
declaredMethod.invoke(obj);
}
}
配置文件- prop.properties
classname=com.qcby.MyReflect.Practice2.Student
method=study
Student类:
package com.qcby.MyReflect.Practice2;
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public void study(){
System.out.println(this.name+"正在学习");
}
}
Teacher类:
package com.qcby.MyReflect.Practice2;
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 +
'}';
}
public void teach(){
System.out.println(this.name+"正在教书");
}
}