如果有两个变量:
Object obj;
String methodName = "getName";
在不知道obj的类的情况下,我如何调用由methodName识别的方法?
被调用的方法没有参数,只有一个String返回值。它是Java bean的getter。
如果有两个变量:
Object obj;
String methodName = "getName";
在不知道obj的类的情况下,我如何调用由methodName识别的方法?
被调用的方法没有参数,只有一个String返回值。它是Java bean的getter。
当前回答
这听起来像是Java Reflection包可以做到的事情。
http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html
特别是在按名称调用方法下面:
进口数组;*;
public class method2 {
public int add(int a, int b)
{
return a + b;
}
public static void main(String args[])
{
try {
Class cls = Class.forName("method2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod(
"add", partypes);
method2 methobj = new method2();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj
= meth.invoke(methobj, arglist);
Integer retval = (Integer)retobj;
System.out.println(retval.intValue());
}
catch (Throwable e) {
System.err.println(e);
}
}
}
其他回答
索引(快)
您可以使用FunctionalInterface将方法保存在容器中以索引它们。您可以使用数组容器通过数字调用它们,或者使用hashmap通过字符串调用它们。通过这个技巧,可以为方法建立索引,从而更快地动态调用它们。
@FunctionalInterface
public interface Method {
double execute(int number);
}
public class ShapeArea {
private final static double PI = 3.14;
private Method[] methods = {
this::square,
this::circle
};
private double square(int number) {
return number * number;
}
private double circle(int number) {
return PI * number * number;
}
public double run(int methodIndex, int number) {
return methods[methodIndex].execute(number);
}
}
λ语法
你也可以使用lambda语法:
public class ShapeArea {
private final static double PI = 3.14;
private Method[] methods = {
number -> {
return number * number;
},
number -> {
return PI * number * number;
},
};
public double run(int methodIndex, int number) {
return methods[methodIndex].execute(number);
}
}
编辑2022
刚才我在想为你提供一个通用的解决方案,与所有可能的方法与变量数:
@FunctionalInterface
public interface Method {
Object execute(Object ...args);
}
public class Methods {
private Method[] methods = {
this::square,
this::rectangle
};
private double square(int number) {
return number * number;
}
private double rectangle(int width, int height) {
return width * height;
}
public Method run(int methodIndex) {
return methods[methodIndex];
}
}
用法:
methods.run(1).execute(width, height);
对于那些想要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
对我来说,一个非常简单和愚蠢的方法是简单地创建一个方法调用者,就像这样:
public static object methodCaller(String methodName)
{
if(methodName.equals("getName"))
return className.getName();
}
然后当你需要调用这个方法时,简单地输入如下内容
//calling a toString method is unnessary here, but i use it to have my programs to both rigid and self-explanitory
System.out.println(methodCaller(methodName).toString());
您应该使用reflection - init一个类对象,然后是该类中的一个方法,然后在具有可选参数的对象上调用此方法。记住将下面的代码段封装在try-catch块中
希望能有所帮助!
Class<?> aClass = Class.forName(FULLY_QUALIFIED_CLASS_NAME);
Method method = aClass.getMethod(methodName, YOUR_PARAM_1.class, YOUR_PARAM_2.class);
method.invoke(OBJECT_TO_RUN_METHOD_ON, YOUR_PARAM_1, YOUR_PARAM_2);