通过反射调用带有参数的方法

时间:2013-12-06 17:25:00

标签: java reflection

我有以下代码,它允许我在扫描程序中输入我想要调用的Employee getter方法,它将使用反射(方法的名称不应出现在代码中的任何位置)。这适用于getter方法,但我现在需要修改代码以执行类似于setter方法的操作。过去一周我一直试图想办法,但我一直无法做到。任何帮助将不胜感激。

感谢。

public static void main(String[] args) {
    Employee e = Employee.testEmployee();                // a sample employee
    Class cls = e.getClass();
    Scanner scanner = new Scanner (System.in);           // to parse data the user types in
    String nextCommand;

    // until the user enters "quit", get the next input from the user, and if it matches
    // a given command, get the desired information from the employee object
    do {
      System.out.print("Enter command >> ");
      nextCommand = scanner.next();
      Method method = null;
      try{
        method = cls.getMethod(nextCommand);
      }
      catch(NoSuchMethodException x) {
      }
      try{
        System.out.println(method.invoke(e));
      }
      catch(IllegalAccessException x) {
      }
      catch(java.lang.reflect.InvocationTargetException x) {
      }
      catch(NullPointerException x) {
      }
    } while (! nextCommand.equals("quit"));
  }

3 个答案:

答案 0 :(得分:2)

这是一个代码示例,可以实现您想要实现的目标:

public class Test {
    private static HashSet<Class<?>> classes = new HashSet<>();

    static {
        classes.add(String.class);
        classes.add(Integer.class);
        classes.add(GregorianCalendar.class);
    }

    public static void main(String[] args) throws NoSuchMethodException,
            SecurityException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {
        X obj = new X();
        obj.setField("lala");
        Method method = obj.getClass().getMethod("getField", null);
        System.out.println(method.invoke(obj, null));

        Method setMethod = getWorkingMethod(obj);
        setMethod.invoke(obj, "who let the dogs out");
        System.out.println(obj.getField());
    }

    private static Method getWorkingMethod(Object obj) {
        Method method = null;
        for (Class<?> c : classes) {
            try {
                method = obj.getClass().getMethod("setField", c);
            } catch (NoSuchMethodException | SecurityException e) {
                continue;
            }
            if(method != null){
                return method;
            }
        }

        throw new IllegalArgumentException("No such method found!");
    }
}

class X {
    private String stringField;

    public void setField(String s) {
        stringField = s;
    }

    public String getField() {
        return stringField;
    }
}

输出:

  

拉​​拉
  谁让狗出去

注意:

  • 创建一个存储HashSet个对象的集合(我使用Class<?>)。您将使用这些来迭代各种可能性,并查看是否存在具有该参数的方法。

  • 使用try-catch查看方法是否存在(当找不到它时会抛出异常)。

  • 这不适用于重载方法。如果这是您的情况,您将不得不进行调整。我希望它没有问题,因为你说这是针对setter(通常没有重载)。

答案 1 :(得分:0)

您可以通过反射直接访问getter来避免调用setterField方法。

Field对象有各种getset方法,可用于操作字段值。

请参阅:http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getField%28java.lang.String%29

示例

import java.lang.reflect.Field;


public class MyObject {

    private String fieldA;


    public String getFieldA() {
        return fieldA;
    }


    public void setFieldA(String fieldA) {
        this.fieldA = fieldA;
    }


    public static void main(String[] args) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {

        MyObject myObject = new MyObject();
        myObject.setFieldA("Test");

        Class clazz = myObject.getClass();

        Field field = clazz.getDeclaredField("fieldA");
        field.setAccessible(true);

        String fieldA = (String) field.get(myObject);
        System.out.println(fieldA);

        field.set(myObject, "Test2");
        fieldA = (String) field.get(myObject);

        System.out.println(fieldA);
        field.setAccessible(false); //be sure to return field to private
    }
}

答案 2 :(得分:0)

java中的分辨率(方法或字段解析)会使执行时间减慢“10或100的订单”,因此不是智能设计决策。因此,在开始时解析一次缓存方法实例,并从缓存中执行它。避免使用反射进行频繁查找。