java反射机制

来源:互联网 发布:wemall java版 编辑:程序博客网 时间:2024/06/07 03:15

反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和方法并且显示出来。这个能特定我们不常看到,但是在其他的比如C或者C++语言中很不就存在这个特性。一个常见的例子是在JavaBean中,一些组件可以通过一个构造器来操作。这个构造器就是用的反射在动态加载的时候来获取的java中类的属性的。

Java语言允许通过程序化的方式间接对Class进行操作,Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数、属性和方法等。Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能,这就为使用程序化方式操作Class对象开辟了途径。


Java反射机制主要提供了以下功能:
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法;
在运行时调用任意一个对象的方法;生成动态代理。

简单实例

package com.baobaotao.reflect; public class Car {     private String brand;     private String color;     private int maxSpeed;      //①默认构造函数     public Car(){}      //②带参构造函数     public Car(String brand,String color,int maxSpeed){          this.brand = brand;         this.color = color;         this.maxSpeed = maxSpeed;     }      //③未带参的方法     public void introduce() {         System.out.println("brand:"+brand+";color:"+color+";maxSpeed:" +maxSpeed);     }      //省略参数的getter/Setter方法      … }

一般情况下,我们会使用如下的代码创建Car的实例:

Car car = new Car(); car.setBrand("红旗CA72");
Car car = new Car("红旗CA72","黑色");

以上两种方法都采用传统方式的直接调用目标类的方法,下面我们通过Java反射机制以一种更加通用的方式间接地操作目标类:

package com.baobaotao. reflect; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectTest {     public static Car  initByDefaultConst() throws Throwable     {         //①通过类装载器获取Car类对象         ClassLoader loader = Thread.currentThread().getContextClassLoader();          Class clazz = loader.loadClass("com.baobaotao.reflect.Car");            //②获取类的默认构造器对象并通过它实例化Car         Constructor cons = clazz.getDeclaredConstructor((Class[])null);          Car car = (Car)cons.newInstance();           //③通过反射方法设置属性         Method setBrand = clazz.getMethod("setBrand",String.class);                 setBrand.invoke(car,"红旗CA72");               Method setColor = clazz.getMethod("setColor",String.class);         setColor.invoke(car,"黑色");               Method setMaxSpeed = clazz.getMethod("setMaxSpeed",int.class);         setMaxSpeed.invoke(car,200);                 return car;     }     public static void main(String[] args) throws Throwable {         Car car = initByDefaultConst();         car.introduce();     } }

输出结果:
brand:红旗CA72;color:黑色;maxSpeed:200

这说明我们完全可以通过编程方式调用Class的各项功能,这和直接通过构造函数和方法调用类功能的效果是一致的,只不过前者是间接调用,后者是直接调用罢了。

在ReflectTest中,使用了几个重要的反射类,分别是ClassLoader、Class、Constructor和Method,通过这些反射类就可以间接调用目标Class的各项功能了。在①处,我们获取当前线程的ClassLoader,然后通过指定的全限定类“com.baobaotao.beans.Car”装载Car类对应的反射实例。在②处,我们通过Car的反射类对象获取Car的构造函数对象cons,通过构造函数对象的newInstrance()方法实例化Car对象,其效果等同于new Car()。在③处,我们又通过Car的反射类对象的getMethod(String methodName,Class paramClass)获取属性的Setter方法对象,第一个参数是目标Class的方法名;第二个参数是方法入参的对象类型。获取方法反射对象后,即可通过invoke(Object obj,Object param)方法调用目标类的方法,该方法的第一个参数是操作的目标类对象实例;第二个参数是目标方法的入参。

粗体所示部分的信息即是通过反射方法操控目标类的元信息,如果我们将这些信息以一个配置文件的方式提供,就可以使用Java语言的反射功能编写一段通用的代码对类似于Car的类进行实例化及功能调用操作了。

IOC(Inverse of
Control)可翻译为“控制反转”,但大多数人都习惯将它称为“依赖注入”。在Spring中,通过IOC可以将实现类、参数信息等配置在其对应的配置文件中,那么当需要更改实现类或参数信息时,只需要修改配置文件即可,这种方法在上例的基础上更进一步的降低了类与类之间的耦合。我们还可以对某对象所需要的其它对象进行注入,这种注入都是在配置文件中做的,Spring的IOC的实现原理利用的就是Java的反射机制

0 0
原创粉丝点击