使用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);
    }
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Java反射机制是Java语言的一种特性,它允许程序在运行时动态地获取类的信息并且操作类中的成员变量方法构造函数等。但是,在使用反射机制的过程中,如果不小心操作不当,就可能会导致类中的数据丢失。这主要是因为反射机制可以突破Java语言的访问控制机制,可以访问私有成员变量方法,而直接修改类中的数据可能会破坏类的封装性,从而导致数据丢失。 例如,如果使用反射机制直接修改了一个类的私有成员变量,而没有经过该类提供的方法进行修改,那么这个类中的数据就有可能会丢失。因此,在使用反射机制时,需要注意遵守Java语言的封装原则,尽可能使用该类提供的方法进行操作,避免直接修改类中的数据。 ### 回答2: Java反射是一种强大的编程技术,它允许我们在运行时动态地获取和操作类的信息,包括类的字段(成员变量)、方法构造函数等。然而,有时候在使用反射时可能会遇到类中数据丢失的情况。 一种可能的原因是使用反射时未正确地获取类的字段。在Java中,类的字段可以分为实例字段和静态字段。如果我们想要获取实例字段的值,需要先通过Class类的实例方法getDeclaredField()或getField()来获取字段对象,然后再通过字段对象调用get()方法获取字段的值。同样,如果想要获取静态字段的值,需要通过Class类的静态方法getField()来获取字段对象,然后再通过字段对象调用get()方法获取字段的值。如果没有正确地获取字段对象或者没有正确地调用get()方法,就会导致获取到的字段值为空或未知。 另外一种可能的原因是在使用反射时未正确地读取或修改字段的访问权限。在Java中,类的字段可以有不同的访问权限,如public、private、protected和default(默认,即无修饰符)。如果字段的访问权限为private,那么在使用反射时需要通过setAccessible(true)将字段的可访问性设置为true,才能正确地读取和修改字段的值。如果没有正确地设置字段的可访问性,就会导致无法读取或修改字段的值,从而造成类中数据丢失的问题。 综上所述,使用Java反射时出现类中数据丢失的原因可能有:未正确地获取字段对象或调用get()方法,以及未正确地读取或修改字段的访问权限。为避免类中数据丢失的问题,在使用反射时我们应该仔细检查和确认获取字段的方式是否正确,并根据字段的访问权限设置字段的可访问性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值