如果有两个变量:

Object obj;
String methodName = "getName";

在不知道obj的类的情况下,我如何调用由methodName识别的方法?

被调用的方法没有参数,只有一个String返回值。它是Java bean的getter。


当前回答

对于jooR,它仅仅是:

on(obj).call(methodName /*params*/).get()

这里有一个更详细的例子:

public class TestClass {

    public int add(int a, int b) { return a + b; }
    private int mul(int a, int b) { return a * b; }
    static int sub(int a, int b) { return a - b; }

}

import static org.joor.Reflect.*;

public class JoorTest {

    public static void main(String[] args) {
        int add = on(new TestClass()).call("add", 1, 2).get(); // public
        int mul = on(new TestClass()).call("mul", 3, 4).get(); // private
        int sub = on(TestClass.class).call("sub", 6, 5).get(); // static
        System.out.println(add + ", " + mul + ", " + sub);
    }
}

这个打印:

3, 12, 1

其他回答

从通俗的角度来说,它应该是这样的:

java.lang.reflect.Method method;
try {
  method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) { ... }
  catch (NoSuchMethodException e) { ... }

参数确定你需要的非常具体的方法(如果有几个重载可用,如果方法没有参数,只给出methodName)。

然后通过调用调用该方法

try {
  method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) { ... }
  catch (IllegalAccessException e) { ... }
  catch (InvocationTargetException e) { ... }

同样,如果没有.invoke中的参数,请省略。但是是的。阅读Java反射

try {
    YourClass yourClass = new YourClass();
    Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
    method.invoke(yourClass, parameter);
} catch (Exception e) {
    e.printStackTrace();
}

假设您从同一个类中的一个静态方法调用一个静态方法。为此,您可以对以下代码进行示例。

class MainClass
{
  public static int foo()
  {
    return 123;
  }

  public static void main(String[] args)
  {
    Method method = MainClass.class.getMethod("foo");
    int result = (int) method.invoke(null); // answer evaluates to 123
  }
}

为了解释一下,因为我们在这里不打算执行真正的面向对象编程,因此避免创建不必要的对象,所以我们将利用class属性来调用getMethod()。

然后,我们将为invoke()方法传入null,因为我们没有对象来执行此操作。

最后,因为我们程序员,知道我们期待的是一个整数,那么 我们显式地将invoke()调用的返回值转换为一个整数。

现在您可能想知道:“用Java进行所有这些非面向对象的编程到底有什么意义?”

我的用例是用Java解决Project Euler问题。我有一个包含所有解决方案的Java源文件,我想传入命令行参数,以确定要运行哪个Project Euler问题。

对于那些想要Java 7中简单的代码示例的人:

狗类:

package com.mypackage.bean;

public class Dog {
    private String name;
    private int age;

    public Dog() {
        // empty constructor
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public void printDog(String name, int age) {
        System.out.println(name + " is " + age + " year(s) old.");
    }
}

ReflectionDemo类:

package com.mypackage.demo;

import java.lang.reflect.*;

public class ReflectionDemo {

    public static void main(String[] args) throws Exception {
        String dogClassName = "com.mypackage.bean.Dog";
        Class<?> dogClass = Class.forName(dogClassName); // convert string classname to class
        Object dog = dogClass.newInstance(); // invoke empty constructor

        String methodName = "";

        // with single parameter, return void
        methodName = "setName";
        Method setNameMethod = dog.getClass().getMethod(methodName, String.class);
        setNameMethod.invoke(dog, "Mishka"); // pass arg

        // without parameters, return string
        methodName = "getName";
        Method getNameMethod = dog.getClass().getMethod(methodName);
        String name = (String) getNameMethod.invoke(dog); // explicit cast

        // with multiple parameters
        methodName = "printDog";
        Class<?>[] paramTypes = {String.class, int.class};
        Method printDogMethod = dog.getClass().getMethod(methodName, paramTypes);
        printDogMethod.invoke(dog, name, 3); // pass args
    }
}

输出: 米什卡3岁了。


你可以用这种方法调用带形参的构造函数:

Constructor<?> dogConstructor = dogClass.getConstructor(String.class, int.class);
Object dog = dogConstructor.newInstance("Hachiko", 10);

或者,您可以删除

String dogClassName = "com.mypackage.bean.Dog";
Class<?> dogClass = Class.forName(dogClassName);
Object dog = dogClass.newInstance();

,做

Dog dog = new Dog();

Method method = Dog.class.getMethod(methodName, ...);
method.invoke(dog, ...);

推荐阅读:创建新类实例

对于jooR,它仅仅是:

on(obj).call(methodName /*params*/).get()

这里有一个更详细的例子:

public class TestClass {

    public int add(int a, int b) { return a + b; }
    private int mul(int a, int b) { return a * b; }
    static int sub(int a, int b) { return a - b; }

}

import static org.joor.Reflect.*;

public class JoorTest {

    public static void main(String[] args) {
        int add = on(new TestClass()).call("add", 1, 2).get(); // public
        int mul = on(new TestClass()).call("mul", 3, 4).get(); // private
        int sub = on(TestClass.class).call("sub", 6, 5).get(); // static
        System.out.println(add + ", " + mul + ", " + sub);
    }
}

这个打印:

3, 12, 1