如果有两个变量:
Object obj;
String methodName = "getName";
在不知道obj的类的情况下,我如何调用由methodName识别的方法?
被调用的方法没有参数,只有一个String返回值。它是Java bean的getter。
如果有两个变量:
Object obj;
String methodName = "getName";
在不知道obj的类的情况下,我如何调用由methodName识别的方法?
被调用的方法没有参数,只有一个String返回值。它是Java bean的getter。
当前回答
首先,不要。避免使用这类代码。它往往是非常糟糕的代码,也不安全(请参阅安全编码指南的第6节) Java编程语言,版本2.0)。
如果你必须这样做,你更喜欢java。豆子要反射。Beans包装反射,允许相对安全和常规的访问。
其他回答
从通俗的角度来说,它应该是这样的:
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反射
如果多次调用,则可以使用Java 7中引入的新方法句柄。现在我们开始你的方法返回一个字符串:
Object obj = new Point( 100, 200 );
String methodName = "toString";
Class<String> resultType = String.class;
MethodType mt = MethodType.methodType( resultType );
MethodHandle methodHandle = MethodHandles.lookup().findVirtual( obj.getClass(), methodName, mt );
String result = resultType.cast( methodHandle.invoke( obj ) );
System.out.println( result ); // java.awt.Point[x=100,y=200]
这听起来像是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);
}
}
}
假设您从同一个类中的一个静态方法调用一个静态方法。为此,您可以对以下代码进行示例。
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, ...);
推荐阅读:创建新类实例