在java中动态调用类方法?

时间:2013-09-13 05:18:13

标签: java

是否可以从java动态调用类的方法?

例如,假设我有一个类的引用,例如字符串:'com.foo.Bar',或com.foo.Bar.class,或者其他任何需要的东西......)。我有一个数组/字符串列表,例如[First, Last, Email]

我想简单地遍历这个数组,并在我引用的类上调用方法'validate' + element。 E.g:

MyInterface item = //instantiate the com.foo.Bar class here somehow, I'm not sure how.

item.validateFirst();
item.validateLast();
item.validateEmail();

我希望上面的代码行动态发生,因此我可以将引用更改为其他类,并且我的字符串列表中的名称可以更改,但它仍会在任何类上调用validate + name方法它有参考。

这可能吗?

6 个答案:

答案 0 :(得分:4)

您可以编写类似这样的内容...它将类的名称作为字符串作为参数,方法名称及其参数

private static String invoke(String aClass, String aMethod, Class<?>[] params,
            Object[] args) throws Exception {
        String resp = "";
        Class<?> c = Class.forName(aClass);
        Method m = c.getDeclaredMethod(aMethod, params);
        Object i = c.newInstance();
        resp = m.invoke(i, args).toString();

        return resp;
}

您还可以参考关于反射的oracle教程...它演示了如何调用方法 http://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html

答案 1 :(得分:2)

最简单的方法是使用reflection

...鉴于

package com.foo;

public class Bar {

    public void validateFirst() {
        System.out.println("validateFirst");
    }

    public void validateLast() {
        System.out.println("validateLast");
    }

    public void validateEmail() {
        System.out.println("validateEmail");
    }

}

您可以使用类似......

的内容
String methodNames[] = new String[]{"First", "Last", "Email"};
String className = "com.foo.Bar";
try {

    Class classRef = Class.forName(className);
    Object instance = classRef.newInstance();

    for (String methodName : methodNames) {

        try {

            Method method = classRef.getDeclaredMethod("validate" + methodName);
            method.invoke(instance);

        } catch (NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) {
            ex.printStackTrace();
        }

    }

} catch (ClassNotFoundException | InstantiationException | IllegalAccessException ex) {
    ex.printStackTrace();
}

查找方法并执行它们。

您需要决定处理错误的最佳方式及其对您的意义,但将这个想法扩展为可重用的方法并不困难......

更新了评论中讨论的概念

...鉴于

public interface Validator {
    public boolean isValid(Properties formProperties);
}

我们可以创建一个或多个......

public class UserRegistrationValidator implements Validator {
    public boolean isValid(Properties formProperties) {
        boolean isValid = false;
        // Required fields...
        if (formProperties.containsKey("firstName") && formProperties.containsKey("lastName") && formProperties.containsKey("email")) {
            // Further processing, valid each required field...
        }
        if (isValid) {
            // Process optional parameters
        }
        return isValid;
    }
}

然后,从我们的输入控制器,我们可以查看并验证所需的表格

public class FormController ... {

    private Map<String, Validator> validators;

    public void validForm(String formName, Properties formProperties) {
        boolean isValid = false;
        Validator validator = validators.get(formName);
        if (validator != null) {
            isValid = validate.isValid(formProperties);
        }
        return isValid;
    }

}

当然,您需要提供一些方法来注册Validators,并且根据您使用的骨干框架和您可以使用的参数(您不必使用{{},可能存在差异。 1}},但它基本上只是Properties ...)

答案 2 :(得分:1)

可以使用reflection

  1. 首先,您从FQN创建一个新类(完全限定名称,包括包的类名)。

  2. 然后,您遍历elements并调用商品上的"validate"方法。

  3.     Class<?> clazz = Class.forName("com.foo.Bar");
        Object item = clazz.newInstance(); 
        for (String element : elements) {
            Method method = clazz.getDeclaredMethod("validate" + element);
            method.invoke(item);
        }
    

答案 3 :(得分:1)

你可以使用反射,但我最喜欢的方法是使用beanutils,例如:

Bar b1 = //...
BeanUtils.getProperty(b1, "first");
BeanUtils.getProperty(b1, "last");

请注意,您的类必须符合javabean约定。您可以阅读有关beanutils on this blog post的更多信息(免责声明我是博客作者)

答案 4 :(得分:1)

如果您事先知道班级的名称,请使用Class.forName(yourClassname) 这样,您可以调用该类,然后,您可以调用其方法。

答案 5 :(得分:0)

是的,使用反射。 在您的对象上使用Class.getDeclaredMethod

Object validator = <your object instance>;
final String[] values = {
  "Item1","Item2","Item3"
}
for(final String s : values) {
  Method m = validator.getDeclaredMethod("validate" + s,String.class);
  try {
    Object result = m.invoke(validator, s);
  }
  catch(ex) {}
}