Java反射机制

Java反射机制


一、什么是反射?

一般来讲,java从源码到运行有三个阶段,如下图所示:

Created with Raphaël 2.1.0 源代码 字节码 机器码

其中从源代码到字节码的过程是在编译期完成的,从字节码到机器码是在执行期完成的。反射就是可以在执行期动态地获取类的实例、属性、方法并且能够调用类的方法的机制。

二、反射的主要用途

根据反射的定义可以看出,反射的作用主要有两个

  • 编译期间无法确定要调用的类是哪个,需要通过配置文件读入(实例:Spring框架的IOC机制)

    Class<?> cls=Class.forName("XXX.XXXX")
  • 在执行期,需要临时获取某个类的私有属性或方法

    Class<?> cls=obj.getClass();
    Field field=cls.getDeclaredField("xxx");
    field.setAccessible(true);
    T value=field.get(obj)

三、反射的基本用法

基本用法都以MethodClass类举例。

class MethodClass {
    private final int fuck=3;
    private int duck;
    public MethodClass(int duck) {
        this.duck=duck;
    }
    public static void test(){
        System.out.println("static method");
    }
    public int add(int a,int b) {
        return a+b;
    }
    protected int sub(int a,int b) {
        return a-b;
    }
    private int mult(int a,int b) {
        return a*b;
    }
    @Override
    public String toString() {
        return duck+":"+fuck;
    }
}

1. 获得class对象

Class<?> cls_forName=Class.forName("MethodClass");
Class<?> cls_class=MethodClass.class;
MethodClass methodClass=new MethodClass(2);
Class<?> cls_getClass=methodClass.getClass();

这三种方式都可以获得class对象,根据实际场合选择。
2. 创建实例

//通过Class对象的newInstance方法直接获取实例对象,这种方式不能传入构造参数
Object obj=cls_forName.newInstance();
//生成构造器,int.class为obj_params构造器参数的类型
Constructor constructor=cls_forName.getConstructor(int.class);
//通过构造器生成实例对象并传入参数
Object obj_params=constructor.newInstance(2);

3. 判断是否实例是否属于某一类型

 boolean flag=cls_class.isInstance(obj);

4. 获取类的成员变量信息

//getFields方法可以获得class对象的所有公有属性及父类、超类的公有属性
Field[] fields=cls_forName.getFields();
//getDeclaredFields方法可以获得class对象的所有属性(公有、私有、保护、默认),但不能获取父类的属性
Field[] declareFields=cls_forName.getDeclaredFields();
//获取指定名称的属性,区别同上
Field field=cls_forName.getField("fuck");
Field declareField=cls_forName.getDeclaredField("duck");

5. 获取实例的成员变量值

//设置为true,表示无需权限检查,即可调用私有属性
declareField.setAccessible(true);
//获取declafield属性的值
declareField.get(obj);
//获取静态属性field的值
field.get(cls_forName);

6. 获取类的方法信息

//区别同上
Method[] methods=cls_forName.getMethods();
Method[] declareMethods=cls_forName.getDeclaredMethods();
Method declareMethod=cls_forName.getDeclaredMethod("mult", int.class, int.class);
Method method=cls_forName.getMethod("test",int.class,int.class);

7. 调用方法

//调用obj的mult方法,返回值为8
declareMethod.invoke(obj,2,4);
//调用静态方法,输出"static method"
method.invoke(cls_forName);

8. 利用反射创建数组
数组在反射中是比较特殊的类型,下面是一个示例

Object obj_params1=constructor.newInstance(1);
Object obj_params2=constructor.newInstance(2);
Object obj_params3=constructor.newInstance(3);
Object array=Array.newInstance(cls_forName,4);
Array.set(array,1,obj_params1);
Array.set(array,2,obj_params2);
Array.set(array,3,obj_params3);
//输出"2:3"
Array.get(array,2);

参考

http://www.cnblogs.com/Eason-S/p/5851078.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值