9.反射的基本原理
1.反射的原理
* 应用在一些通用性比较高的代码中
* 例如后面学到的框架,大多数都是使用反射来实现的
* 在框架开发中,都是基于配置文件开发
在配置文件中配置了类,可以通过反射得到类中的所有内容,可以让类中的某些方法来执行
* 类中的所有内容:属性、没有参数的构造方法、有参数的构造方法、普通方法
* 画图分析反射的原理
* 首先需要把java文件保存到本地硬盘上 .java
* 编译java文件,成.class文件
* 万事万物都是对象,class文件在内存中使用class类表示
* 当使用反射时候,首先需要获取到class类,得到这个类之后,就可以得到class文件中的所有内容
* 属性通过一个类 Field 表示
* 构造方法通过一个类 Constructor 表示
* 普通方法通过一个类 Method类 表示
2.实例
Persion类
package Day5; public class Persion { //属性 private String id; private String name; //没有参数的构造方法 public Persion() {} //有参数的构造方法 public Persion(String id , String name) { this.id = id; this.name = name; } //普通方法 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
(1)获取class类的三种方式
public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { Class c1 = Persion.class; Class c2 = new Persion().getClass(); //注意参数为包名+类名,推荐使用这种方式 Class c3 = Class.forName("Day5.Persion"); } }
(2)操作无参数的构造方法
@Test public void test1() throws Exception { //获取calss类 Class c3 = Class.forName("Day5.Persion"); //获取persion类的实例(当创建persion实例的时候,无参数的构造方法已经运行了) Persion persion = (Persion) c3.newInstance(); //通过persion实例调用里面的普通的方法 persion.setName("张三"); //我们来查看我们设置的值是否成功 System.out.println(persion.getName()); }
(3)操作有参数的构造方法
@Test public void test2() throws Exception { //获取class类 Class c3 = Class.forName("Day5.Persion"); //获取有参数的构造方法(c3.getConstructors(); 获取所有的构造方法) //里面的参数是使用class形式传递的(persion有参的构造方法是String类型) //java.lang.reflect.Constructor Constructor cs = c3.getConstructor(String.class,String.class); //通过有参数的构造方法获取persion实例 Persion persion = (Persion) cs.newInstance("101","张三"); //输出我们设置的值 System.out.println(persion.getId()+" "+persion.getName()); }
(4)操作属性
@Test public void test3() throws Exception { //获取class类 Class c3 = Class.forName("Day5.Persion"); //获取persion的实例 Persion persion = (Persion) c3.newInstance(); //获取name属性 Field field = c3.getDeclaredField("name"); //因为我们定义的属性是私有的,所以不能直接操作,我们设置为可以操作私有属性 field.setAccessible(true); //设置name的值为张三 field.set(persion, "张三"); //输出name属性的值 System.out.println(field.get(persion)); }
(5)操作普通方法(如果方法为私用的。需要设置method.setAccessible(true))
注意:当使用反射操作静态的方法的时候invokie方法的第一个参数里面写一个null
@Test public void test4() throws Exception { //获取class类 Class c3 = Class.forName("Day5.Persion"); //获取persion的实例 Persion persion = (Persion) c3.newInstance(); //获取setName普通方法(参数一:方法名 参数二:方法里面的参数类型) Method method = c3.getDeclaredMethod("setName", String.class); //通过获取的setName设置值 method.invoke(persion, "张三"); //输出 System.out.println(persion.getName()); }