公共技术点之 Java反射 Reflection

公共技术之 Java反射 Reflection1. 了解Java中的反射1.1 什么是Java的反射

Java反射是可以让我们在运行时获取类的函数、字段、父类、接口等Class内部信息的机制。通过反射还可以让我们在运行期实例化对象,调用方法,通过调用get/set方法获取变量的值,即使方法或字段是私有的的也可以通过反射的形式调用,这种“看透class”的能力被称为内省,这种能力在框架开发中尤为重要。 有些情况下,我们要使用的类在运行时才会确定,这个时候我们不能在编译期就使用它,因此只能通过反射的形式来使用在运行时才存在的类(该类符合某种特定的规范,例如JDBC),这是反射用得比较多的场景。 还有一个比较常见的场景就是编译时我们对于类的内部信息不可知,必须得到运行时才能获取类的具体信息。比如ORM框架,在运行时才能够获取类中的各个字段,然后通过反射的形式获取其字段名和值,存入数据库。这也是反射比较经典应用场景之一。

1.2 Class类

那么既然反射是操作Class信息的,Class又是什么呢?

当我们编写完一个Java项目之后,所有的Java文件都会被编译成一个.class文件,这些Class对象承载了这个类型的父类、接口、构造函数、方法、字段等原始信息,这些class文件在程序运行时会被ClassLoader加载到虚拟机中。当一个类被加载以后,Java虚拟机就会在内存中自动产生一个Class对象。我们通过new的形式创建对象实际上就是通过这些Class来创建,只是这个过程对于我们是不透明的而已。 下面的章节中我们会为大家演示反射的一些常用api,从代码的角度理解反射。

2. 反射Class以及构造对象2.1 获取Class对象

在你想检查一个类的信息之前,你首先需要获取类的Class对象。Java中的所有类型包括基本类型,即使是数组都有与之关联的Class类的对象。如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的Class对象。

Class<?> myObjectClass = MyObject.class;

如果你已经得到了某个对象,但是你想获取这个对象的Class对象,那么你可以通过下面的方法得到:

Student me = new Student(“mr.simple”);Class<?> clazz = me.getClass();

如果你在编译期获取不到目标类型,但是你知道它的完整类路径,那么你可以通过如下的形式来获取Class对象:

Class<?> myObjectClass = Class.forName(“com.simple.User”);

在使用Class.forName()方法时,你必须提供一个类的全名,,这个全名包括类所在的包的名字。例如User类位于com.simple包,那么他的完整类路径就是com.simple.User。 如果在调用Class.forName()方法时,没有在编译路径下(classpath)找到对应的类,那么将会抛出ClassNotFoundException。

接口说明

<?> forName (String className)<?> forName (String className, boolean shouldInitialize, ClassLoader classLoader)2.2 通过Class对象构造目标类型的对象

一旦你拿到Class对象之后,你就可以为所欲为了!当你善用它的时候它就是神兵利器,当你心怀鬼胎之时它就会变成恶魔。但获取Class对象只是第一步,我们需要在执行那些强大的行为之前通过Class对象构造出该类型的对象,然后才能通过该对象释放它的能量。 我们知道,在java中药构造对象,必须通过该类的构造函数,那么其实反射也是一样一样的。但是它们确实有区别的,通过反射构造对象,我们首先要获取类的Constructor(构造器)对象,然后通过Constructor来创建目标类的对象。还是直接上代码的。

classForName() {try {// 获取Class对象Class<?> clz = Class.forName(“org.java.advance.reflect.Student”);// 通过Class对象获取Constructor,Student的构造函数有一个字符串参数,// 因此这里需要传递参数的类型 ( Student类见后面的代码 )Constructor<?> constructor = clz.getConstructor(String.class);// 通过Constructor来创建Student对象Object obj = constructor.newInstance(“mr.simple”);System.out.println(” obj : ” + obj.toString());} catch (Exception e) {e.printStackTrace();}}

通过上述代码,我们就可以在运行时通过完整的类名来构建对象。

获取构造函数接口

<T> getConstructor (Class…<?> parameterTypes)// 获取目标类所有的公有构造函数

注意,当你通过反射获取到Constructor、Method、Field后,在反射调用之前将此对象的 accessible 标志设置为true,以此来提升反射速度。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。例如 :

.= Student.class.getMethod(“learn”, String.class); learnMethod.setAccessible(true);

由于后面还会用到Student以及相关的类,我们在这里就先给出它们的代码吧。 Person.java

public class Person {String mName;public Person(String aName) {mName = aName;}(String friendName) {System.out.println(mName + ” say hello to ” + friendName);}() {System.out.println(“My name is ” + mName);}() {System.out.println(” take breathe “);}}

Student.java

{// 年级int mGrade;public Student(String aName) {super(aName);}public Student(int grade, String aName) {super(aName);mGrade = grade;}(String course) {System.out.println(mName + ” learn ” + course);}() {System.out.println(” takeAnExamination “);}public String toString() {return ” Student : ” + mName;}

Breathe.java

Breathe {();}

Examination.java

Examination {();}3 反射获取类中函数3.1 获取当前类中定义的方法你会发现,曾经以为很难做到的事情,

公共技术点之 Java反射 Reflection

相关文章:

你感兴趣的文章:

标签云: