一. 简介
在程序运行阶段, 动态获取一个类中的属性或者方法, 把这种机制成为反射机制. 可以说, 没有反射就没有Java的任何框架
二. 应用
产生对象
假设有一个Student对象
public class Student {private String name;public int age;static int nationality;public Student() {System.out.println("Student类的无参构造");}Student(String name) {System.out.println("Student的一个参数的有参构造");}private Student(String name,int age) {this.name = name;this.age = age;System.out.println("Student类的有参构造");}public void fun(int[] arr) {System.out.println("public权限的成员方法 fun");}private String getName() {return this.name;}public static void test() {System.out.println("Student的静态方法test");}
}
*获取class对象
要用反射操作某个类, 需要先获取该类的class对象
获取class对象的三个方式:
①Class<类名> cls = (Class<类名>) Class.forName("包名.类名")
②Class<类名> cls = Student.class
③Class<类名> cls = (Class<类名>) new Student().getClass()
例如Student对象的获取:
Class<Student> cls1 = (CLass<Student>) Class.forName("reflect.Student");
Class<Student> cls2 = Student.class;
Class<Student> cls3 = (Class<Student>) new Student().getClass();
不过一般使用第②个方法,写法简单
通过反射产生对象
Class类的newInstance()方法
例如对于Student类: Student stu1 = cls2.newInstance();
默认调用的是无参构造, 而且该构造方法必须是public
权限
通过Constructor调用构造方法
Constructor类是Java中利用反射操作构造方法的类
两个方法:
①getConstructor(参数)
: 获取该类的所有(加s)public权限的构造方法
②getDeclaredConstructor(参数)
: 获取该类的所有(加s)权限的构造方法, 包括private, default权限
Class<Student> cls2 = Student.class;
//获取该类的所有权限的构造方法
Constructor<Student>[] constructors = cls2.getDeclaredConstructors();
//获取私有的有参构造:private Student(String name,int age),参数对应上
Constructor<Student> constructor = cls2.getDeclaredConstructor(String.class, int.class);//破坏封装性,调用私有构造方法
constructor.setAccessible(true);
//要用下面的方法, 不可以用new Student()
Student stu2 = constructor.newInstance("小明",18);
通过反射操作类中方法
①getMethod()
: 获取所有(加s)公共方法
②getDeclaredMethod()
: 获取类中所有(加s)方法
//接着上面
Method[] methods = cls2.getDeclaredMethods();
//此时数组里就包含了所有的方法以及权限//调用普通方法与静态方法
//调用普通方法都要产生对象
Student student = cls2.newInstance();
//获取方法(参数1:方法的名字, 后面的参数就是方法的参数)
Method methodFun = cls2.getDeclaredMethod("fun",int[].class);
//调用方法(参数1是对象,后面是方法参数)
methodFun.invoke(student, new int[]{1,2,3,4,5});//通过反射调用静态方法
Method methodTest = cls2.getDeclaredMethod("test");
//不需要对象即可调用
methodTest.invoke(null);
通过反射操作类中属性
①getField()
: 获取所有(加s)public方法
②getDeclaredField()
: 获取所有(加s)方法, 包括private
//获取class对象
Class<Student> cls = Student.class;
//实例化对象
Student stu = cls.newInstance();//用cls.getDeclaredField()获取私有属性
Field nameField = cls.getDeclaredField("name");
//设置name属性为可访问
nameField.setAccessible(true);
//修改该对象的该属性
nameField.set(stu,"bob");//获取public属性
Field ageField = cls.getField("age");
//修改该对象的该属性
ageField.set(stu,88);//获取静态属性
Field nationalityField = cls.getField("nationality");
//修改属性
nationalityField.set(null,"USA");//经过检查,修改都生效了
System.out.println(Student.nationality);