** 注:博主的这篇文章是在学习反射的时间写的若有问题请及时联系博主进行修改 **java
这里也不说一些很官方的语言了,官方的说明看着头痛,总之一句话,就是在JAVA的运行状态的时候,能够对任何一个类进行操做,这是一个能够动态的获取信息和动态的使用某个方法的能力咱们就叫他反射,在家看下名字就知道这项功能有多屌。api
注:Class类表示正在运行的JAVA应用程序的接口;Class类没有构造方法,是由java虚拟机自动建立的。
这里先例举几个经常使用到的方法,这些是咱们此次教程所须要的方法,不是不少,其余的我在之后的文章中写出。
首先我建立个Student.java的类,里面有三个属性(name,age,xb),看代码:
package net.cncandy.test; public class Student { private String name; private int age; private boolean xb; 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 boolean isXb() { return xb; } public void setXb(boolean xb) { this.xb = xb; } public Student(String name, int age, boolean xb) { super(); this.name = name; this.age = age; this.xb = xb; } public Student() { } }
接下来咱们要建立一个测试的类,我给他取名字叫作TestDeom,大家能够根据本身来建立这个类哦。安全
咱们须要认识三中获取类的方式:函数
当咱们建立好了测试的类后,咱们这里讲解的是反射,咱们固然要经过反射的方式来加载到JVM,这里就须要我上面说的Class.forName的方式来加载,这个方法是返回的一个Class对象。学习
` Class studentClass = Class.forName("net.cncandy.test.Student"); ` > 参数这里面填写的是你的包名加上类的名字,返回的数据要**经过Class类型接受**。这个时候你使用System.out.println(studentClass);打印是否是发现控制台有显示出来类的信息。 好比我这里显示的是 **class net.cncandy.test.Student** 这里的信息和你可能显示不同,能够咱们的包名是不同的,你要对应你本身的
类已经加载到了内存中了,咱们是否是应该建立个Student的对象呢,咱们都知道在平时普通的new一个对象的时候,其实默认是调用了该类的构造方法,那么这里也是如此咱们也须要拿到该类的构造方法,这小结咱们要须要如何获取类的构造方法:测试
咱们看下如何经过无参的构造来实例化对象,这里咱们只须要使用Class的对象点出newInstance()便可,这样系统就会实例化一个对象。this
问:我调用了newInstance(),是如何实例化对象的呢?上面说要经过构造函数,我也没有指定构造函数呀。
答:使用次方法系统会自动寻找类中的无参的构造方法,经过无参的构造来实例化对象。这里你们能够测试下,当你删除类中的无参构造时,你再次运行代码会出现错误。code
Class studentClass = Class.forName("net.cncandy.test.Student"); //加载类 Student student = (Student)studentClass.newInstance(); //实际是使用的无参构造实例化对象 student.setAge(16); //使用类中的方法 System.out.println(student.getAge()); //输出值,验证是否成功复制
输出的结果是16,证实咱们这种实例化对象的方法是对的对象
首先咱们要先拿到带有参数的构造方法,在我上面写的方法列表内有相关的方法,咱们这里使用的是getConstructor()来获取带参的构造,先来了解下代码:blog
Constructor constructor =studentClass.getConstructor(String.class,int.class,boolean.class); Student student = (Student) constructor.newInstance("Candy",20,true); System.out.println(student.getAge());
这里你们看下的,在getConstructor()若是括号额你填的空则是使用的是空参数构造方法,填写参数的意思是由于咱们每一个类中可能会存在大量重名的方法,好比咱们使用的方法重载,这里能够经过参数列表来区分使用的是哪个方法。当你传入了参数的时候,在你使用newInstance时候你会发现代码有提示说让您传入参数,这里的参数就是你平时实例化对象时的实际参数。
咱们这里能够经过参考上面经过有参数的构造来实例化对象的代码来处理使用类中的方法,其实这里的思路是同样的。遵循三个步骤(这里对于我来讲的是那个步骤)1.拿到类中的方法(Look,反射屌不屌)2.给方法传递参数,3.测试是否成功。这里的获取方法的方法是须要传入两个参数
参数一:你须要的方法的名称
参数二:方法参数的类型,有多少写多少,反正代码里面接受的是三个点可编长参数。
最后使用invoke方法来进行使用方法,两个参数:
参数一:上面我们实例化的student。
参数二:你须要往这个方法里面传的值
Method method = clzzClass.getDeclaredMethod("setAge", int.class); method.invoke(user, 20); System.out.println(user.getAge());
最后验证输出的是20
上面方法表格里面给出了获取属性的方法getDeclaredField返回值是Field,咱们这里能够直接经过这个方法传入须要得到的属性名字,
Field field = studentClass.getDeclaredField("name"); field.set(student, "Candy"); System.out.println(student.getName());
固然咱们在设置属性的值的时候咱们是经过set方法来设置的这个里面须要传入两个参数,参数一:Student的对象,参数二:须要设置的值,运行程序能够正确的输出Candy。
注:这个获取属性的时候,若是有的属性在类中是私有的属性,那么咱们在这里修改值的时候会爆出java.lang.IllegalAccessException异常,因此这里咱们还要加一句代码setAccessible(true)这句话是避免安全检查,这里不作多的解释,有兴趣的能够看下源码。