一、概念
反射是在运行期间,动态获取对象的属性和方法
二、相关的类
在Java的反射里主要有以下几个类:Class类,这是反射的起源,反射必须要先获取Class对象,其次是Field类,当我们需要通过反射获取私有字段时就需要用到这个类,Method类,同理我们获取私有方法时就需要用到这个类
三、获取Class对象
要进行反射就必须先获取目标类对应的Class对象,主要有以下三种方法:
我们先定义一个学生类:主要字段有姓名、班级、年龄都是私有,其中一个公开的无参构造方法,一个私有含参构造方法,还有一个私有的eat方法
class Student{
private String name;
private String classes;
private int age;
public Student() {
}
private Student(String name,String classes,int age){
this.name = name;
this.classes = classes;
this.age = age;
}
private void eat(String s){
System.out.println(this.classes + "的" + this.name +"上课偷吃"+s);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", classes='" + classes + '\'' +
", age=" + age +
'}';
}
}
然后我们通过以下三种方法获取Class对象
- 目标类.class
public class GetConstruct {
public static void main(String[] args) {
//1.获取Class对象
Class<?> c1 = Student.class;
Class<?> c2 = new Student().getClass();
Class<?> c3 = Class.forName("Student");
}
}
- 目标类实例.getClass()
- Class.forName(目标类名)
三、反射创建实例
获取到Class实例后就可以通过Class实例的方法来构造目标类的对象
- Class类的newInstance方法
public class GetConstruct {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
//1.获取Class对象
Class<?> c1 = Student.class;
Class<?> c2 = new Student().getClass();
//Class<?> c3 = Class.forName("反射.Student");
//2.创建实例
Student student1 = (Student) c1.newInstance();
}
}
- 通过获取目标类的私有构造方法
先获取Class对象,然后利用他的getDeclaredConstructor方法获取私有构造方法
public class GetConstruct {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//1.获取Class对象
Class<?> c1 = Student.class;
Class<?> c2 = new Student().getClass();
//Class<?> c3 = Class.forName("反射.Student");
//2.创建实例
Constructor<?> constructor = c1.getDeclaredConstructor(String.class,String.class,int.class);
constructor.setAccessible(true); //确认获取
Student student = (Student) constructor.newInstance("张三","21级3班",21);//传入参数
//3.验证
System.out.println(student);
}
}
四、反射获取私有字段
依旧先是获取Class对象然后利用反射创建目标类的实例 ,最后使用Field类获取修改字段
public class GetField {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
//1.获取Class对象
Class<?> c1 = Student.class;
//Class<?> c2 = new Student().getClass();
//Class<?> c3 = Class.forName("反射.Student");
//2.创建目标类实例
Constructor<?> constructor = c1.getDeclaredConstructor(String.class,String.class,int.class);
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("张三","21级4班",21);
//3.利用Field类的方法修改字段
Field field = c1.getDeclaredField("name"); //参数传入要获取的字段名
field.setAccessible(true); //确认获取
field.set(student,"李四"); //参数:要修改的目标实例,新字段的值
//4.验证
System.out.println(student);
}
}
五、反射获取私有方法
先获取Class实例,然后创建目标类对象,再通过Method类进行获取,调用 方法获取目类i私有方法
public class GetMethod {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
//1.获取Class对象
Class<?> c1 = Student.class;
//Class<?> c2 = new Student().getClass();
//Class<?> c3 = Class.forName("反射.Student")/;
//2.创建目标类实例
Constructor<?> constructor = c1.getDeclaredConstructor(String.class,String.class,int.class);
constructor.setAccessible(true);
Student student = (Student) constructor.newInstance("张三","21级4班",21);
//3.通过Method方法获取
Method method = c1.getDeclaredMethod("eat",String.class); //参数传入要获取的方法名
method.setAccessible(true); //确认获取
method.invoke(student,"零食"); //传入目标类的实例与函数参数
}
}