使用java反射操作类的构造函数,成员变量和成员方法

 

在java.lang.reflect包中有三个类Field,Method,Constructor.分别描述域,方法,构造器。参考API,关于这三个类的说明。

 

在运行时使用反射分析对象,如果访问的是私有域或是私有方法,私有构造函数,会抛出IllegalAccessException.因为反射机制的默认行为受限于java的访问控制,然而,如果一个java程序没有受到安全管理器的控制,就可以覆盖访问控制。为了达到这个目的,需要调用Field,Method,Constructor对象的setAccessible方法,setAccessible方法是AccessibleObject类的一个方法,是Field,Method,Constructor类的公共超类。

setAccessible(true);

 

不要过多地使用反射:破坏类封装;效率偏低;编译器不容易帮助发现错误,在运行时才会被发现。

我使用反射,是为了写单元测试代码,对运行对象的分析,改变对象的私有域等,达到测试需要的覆盖率。

以下提供代码事例:

测试类:

public   class  RunBing  {
    
private String name;
    
private int age;
    
public String sex;

    
public RunBing() {

    }


    
private RunBing(String name) {
        
this.name = name;
    }


    
public void setName(String name) {
        
this.name = name;
    }


    
public void setAge(int age) {
        
this.age = age;
    }


    
public String getName() {
        
return name;
    }


    
public int getAge() {
        
return age;
    }


    
public String run() {
        
return "run method";
    }


    
private String add() {
        
return "add method";
    }

}

 

 

 


import  java.lang.reflect.Field;
import  java.lang.reflect.Method;
import  java.lang.reflect.Constructor;


public   class  ReflectHelp  {

        
/**
         * 通过构造器取得实例
         * 
@param className 类的全限定名
         * 
@param intArgsClass 构造函数的参数类型
         * 
@param intArgs 构造函数的参数值
         * 
         * 
@return Object 
         
*/

        
public static Object getObjectByConstructor(String className,Class[] intArgsClass,Object[] intArgs){

        Object returnObj
= null;
        
try {
            Class classType 
= Class.forName(className);
            Constructor constructor 
= classType.getDeclaredConstructor(intArgsClass); //找到指定的构造方法
            constructor.setAccessible(true);//设置安全检查,访问私有构造函数必须
            returnObj = constructor.newInstance(intArgs);
        }
 catch (NoSuchMethodException ex) {
            ex.printStackTrace();
        }
 catch (Exception ex) {
            ex.printStackTrace();
        }

        
return returnObj;
    }

    
/**
     * 修改成员变量的值
     * 
@param Object 修改对象
     * 
@param filedName 指定成员变量名
     * 
@param filedValue 修改的值
     *
     * 
@return 
     
*/

    
public static void modifyFileValue(Object object, String filedName,
                                       String filedValue) 
{
        Class classType 
= object.getClass();
        Field fild 
= null;
        
try {
            fild 
= classType.getDeclaredField(filedName);
            fild.setAccessible(
true);//设置安全检查,访问私有成员变量必须
            fild.set(object, filedValue);
        }
 catch (NoSuchFieldException ex) {
            ex.printStackTrace();
        }
 catch (Exception ex) {
            ex.printStackTrace();
        }

    }


    
/**
     * 访问类成员变量
     * 
@param Object 访问对象
     * 
@param filedName 指定成员变量名
     * 
@return Object 取得的成员变量的值
     * 
*/

    
public static Object getFileValue(Object object, String filedName) {
        Class classType 
= object.getClass();
        Field fild 
= null;
        Object fildValue 
= null;
        
try {
            fild 
= classType.getDeclaredField(filedName);
            fild.setAccessible(
true);//设置安全检查,访问私有成员变量必须
            fildValue = fild.get(object);

        }
 catch (NoSuchFieldException ex) {
            ex.printStackTrace();
        }
 catch (Exception ex) {
            ex.printStackTrace();
        }

        
return fildValue;
    }


    
/**
     * 调用类的方法,包括私有
     * 
@param Object 访问对象
     * 
@param methodName 指定成员变量名
     * 
@param type 方法参数类型
     * 
@param value 方法参数指
     * 
@return Object 方法的返回结果对象
     * 
*/

    
public static Object useMethod(Object object, String methodName,
                                   Class[] type, Class[] value) 
{
        Class classType 
= object.getClass();
        Method method 
= null;
        Object fildValue 
= null;
        
try {
            method 
= classType.getDeclaredMethod(methodName, type);
            method.setAccessible(
true);//设置安全检查,访问私有成员方法必须
            fildValue = method.invoke(object, value);

        }
 catch (NoSuchMethodException ex) {
            ex.printStackTrace();
        }
 catch (Exception ex) {
            ex.printStackTrace();
        }

        
return fildValue;
    }



    
public static void main(String[] args) {
        RunBing runbing 
= new RunBing();
        runbing.setName(
"aaa");

        
//访问成员变量
        String value = (String) ReflectHelp.getFileValue(runbing, "sex");
        System.out.println(
"value:" + value);
        
//修改成员变量
        ReflectHelp.modifyFileValue(runbing, "sex""bbb");
        System.out.println(
"value:" + runbing.getName());
        
//检查修改后的变量值
        value = (String) ReflectHelp.getFileValue(runbing, "sex");
        System.out.println(
"value:" + value);

        
//调用方法
        value = (String) ReflectHelp.useMethod(runbing, "add"new Class[] {},
                                               
new Class[] {});
        System.out.println(
"value:" + value);

        
//使用指定构造函数
        Class[] inArgs = new Class[]{String.class};
        Object[] inArgsParms 
= new Object[]{"hanj"};
        RunBing runBing2 
= (RunBing)ReflectHelp.getObjectByConstructor("com.ccit.hj.reflect.RunBing",inArgs,inArgsParms);
        value 
= (String) ReflectHelp.getFileValue(runBing2, "name");
        System.out.println(
"cc -- value:" + value);
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值