当方法名作为字符串给定时,如何调用Java方法?
如果我有两个变量:当方法名作为字符串给定时,如何调用Java方法?,java,reflection,invoke,Java,Reflection,Invoke,如果我有两个变量: Object obj; String methodName = "getName"; 在不知道obj的类的情况下,如何调用由其上的methodName标识的方法 正在调用的方法没有参数,并且有一个字符串返回值。它是Java bean的获取工具。使用反射: Class<?> c = Class.forName("class name"); Method method = c.getDeclaredMethod("method name", parameterTyp
Object obj;
String methodName = "getName";
在不知道obj的类的情况下,如何调用由其上的methodName标识的方法
正在调用的方法没有参数,并且有一个字符串返回值。它是Java bean的获取工具。使用反射:
Class<?> c = Class.forName("class name");
Method method = c.getDeclaredMethod("method name", parameterTypes);
method.invoke(objectToInvokeOn, params);
其中:
类名是类的名称
objectToInvokeOn属于Object类型,是要在其上调用方法的对象
method name是要调用的方法的名称
parameterTypes的类型为类[],并声明该方法采用的参数
params的类型为Object[],并声明要传递给方法的参数
这听起来像是Java反射包可以实现的 特别是在按名称调用方法时: 导入java.lang.reflect.*
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);
}
}
}
从臀部开始编码,可能是这样的:
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中的参数。但是是的。阅读该方法可以这样调用。还有更多的可能性检查反射api,但这是最简单的一种:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Assert;
import org.junit.Test;
public class ReflectionTest {
private String methodName = "length";
private String valueObject = "Some object";
@Test
public void testGetMethod() throws SecurityException, NoSuchMethodException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Method m = valueObject.getClass().getMethod(methodName, new Class[] {});
Object ret = m.invoke(valueObject, new Object[] {});
Assert.assertEquals(11, ret);
}
}
要完成我同事的回答,您可能需要密切关注: 静态或实例调用在一种情况下,您不需要类的实例,在另一种情况下,您可能需要依赖现有的默认构造函数,该构造函数可能存在,也可能不存在 公共或非公共方法调用对于后者,您需要在doPrivileged块内的方法上调用setAccessible,其他 如果您想抛出大量java系统异常,则封装到一个更易于管理的应用程序异常中,因此下面的代码中出现了CCException 下面是一个旧的java1.4代码,它考虑了以下几点:
/**
* Allow for instance call, avoiding certain class circular dependencies. <br />
* Calls even private method if java Security allows it.
* @param aninstance instance on which method is invoked (if null, static call)
* @param classname name of the class containing the method
* (can be null - ignored, actually - if instance if provided, must be provided if static call)
* @param amethodname name of the method to invoke
* @param parameterTypes array of Classes
* @param parameters array of Object
* @return resulting Object
* @throws CCException if any problem
*/
public static Object reflectionCall(final Object aninstance, final String classname, final String amethodname, final Class[] parameterTypes, final Object[] parameters) throws CCException
{
Object res;// = null;
try {
Class aclass;// = null;
if(aninstance == null)
{
aclass = Class.forName(classname);
}
else
{
aclass = aninstance.getClass();
}
//Class[] parameterTypes = new Class[]{String[].class};
final Method amethod = aclass.getDeclaredMethod(amethodname, parameterTypes);
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
amethod.setAccessible(true);
return null; // nothing to return
}
});
res = amethod.invoke(aninstance, parameters);
} catch (final ClassNotFoundException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+CLASS, e);
} catch (final SecurityException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_SECURITY_ISSUE, e);
} catch (final NoSuchMethodException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_NOT_FOUND, e);
} catch (final IllegalArgumentException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ILLEGAL_ARGUMENTS+String.valueOf(parameters)+GenericConstants.CLOSING_ROUND_BRACKET, e);
} catch (final IllegalAccessException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ACCESS_RESTRICTION, e);
} catch (final InvocationTargetException e) {
throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_INVOCATION_ISSUE, e);
}
return res;
}
首先,不要。避免这种代码。它往往是非常糟糕的代码和不安全的,请参见第6节
如果必须这样做,请选择java.bean而不是反射。Beans封装了反射,允许相对安全和常规的访问。对我来说,一个非常简单和简单的方法就是简单地创建一个方法调用方方法,如下所示:
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());
对于那些想要Java 7中直截了当的代码示例的人: 狗类: ReflectionDemo类: 或者,您可以删除
String dogClassName = "com.mypackage.bean.Dog";
Class<?> dogClass = Class.forName(dogClassName);
Object dog = dogClass.newInstance();
建议阅读:您应该在类对象中使用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);
这对我来说很好:
public class MethodInvokerClass {
public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, ClassNotFoundException, InvocationTargetException, InstantiationException {
Class c = Class.forName(MethodInvokerClass.class.getName());
Object o = c.newInstance();
Class[] paramTypes = new Class[1];
paramTypes[0]=String.class;
String methodName = "countWord";
Method m = c.getDeclaredMethod(methodName, paramTypes);
m.invoke(o, "testparam");
}
public void countWord(String input){
System.out.println("My input "+input);
}
}
输出:
我的输入testparam
我可以通过将其名称传递给另一个方法(如main)来调用该方法。请参阅以下代码,这些代码可能会对您有所帮助
public static Method method[];
public static MethodClass obj;
public static String testMethod="A";
public static void main(String args[])
{
obj=new MethodClass();
method=obj.getClass().getMethods();
try
{
for(int i=0;i<method.length;i++)
{
String name=method[i].getName();
if(name==testMethod)
{
method[i].invoke(name,"Test Parameters of A");
}
}
}
catch(Exception ex)
{
System.out.println(ex.getMessage());
}
}
谢谢……我是这样做的:
try {
YourClass yourClass = new YourClass();
Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
method.invoke(yourClass, parameter);
} catch (Exception e) {
e.printStackTrace();
}
使用import java.lang.reflect.*
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);
}
}
}
以下是您如何使用它:
String className = "com.example.helloworld";
String methodName = "print";
Class<?>[] argsTypes = {String.class, String.class};
Object[] methArgs = { "hello", "world" };
launchProcess(className, methodName, argsTypes, methArgs);
SomeClass是类,someVariable是变量。如果多次调用,可以使用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]
Student.java
StudentTest.java
以下是可随时使用的方法: 要调用不带参数的方法,请执行以下操作: 要使用参数调用方法,请执行以下操作: 使用上述方法如下:
package practice;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
public class MethodInvoke {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
String methodName1 = "methodA";
String methodName2 = "methodB";
MethodInvoke object = new MethodInvoke();
callMethodByName(object, methodName1);
callMethodByName(object, methodName2, 1, "Test");
}
public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
object.getClass().getDeclaredMethod(methodName).invoke(object);
}
public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
}
void methodA() {
System.out.println("Method A");
}
void methodB(int i, String s) {
System.out.println("Method B: "+"\n\tParam1 - "+i+"\n\tParam 2 - "+s);
}
}
输出:
索引速度更快
您可以使用FunctionInterface将方法保存在容器中以对其进行索引。您可以使用数组容器通过数字调用它们,或者使用hashmap通过字符串调用它们。通过这个技巧,您可以索引您的方法以更快地动态调用它们
Lambda语法
您还可以使用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);
}
}
这仅仅是:
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
对于从非静态方法调用同一类中的方法的人,请参见以下代码:
class Person {
public void method1() {
try {
Method m2 = this.getClass().getDeclaredMethod("method2");
m1.invoke(this);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public void method2() {
// Do something
}
}
酷,我认为你使用getDeclaredMethod是对的,它可能比getMethod“更安全”。错了。是的,getDeclaredMethod确实适用于私有和受保护的方法。但是:它不适用于超类继承方法中定义的方法。所以,这在很大程度上取决于你想做什么。在许多情况下,您希望它能够工作,而不考虑定义方法的确切类。我应该将类文件放在哪里?最好解释一下EclipseIDE@Mr.Hyde如果我调用的方法根本不接受任何参数,我应该在和method.invoke中放置什么?似乎我还需要提供第二个参数,它应该是某个空的对象数组吗?如果在编译时已经知道该实例,为什么不直接执行className.getName.toString呢?你错过了思考的全部要点。就像我说的,在这种情况下没有必要,但是
t假设你总是知道这个实例是一个坏的编程习惯。@smaine:我建议删除这篇文章。在这种情况下,坏编程更像是一种赞美+1,因为唯一的答案承认OP在他的问题中没有指定参数,因为这也是我要找的。无论是使用还是使用都有点不高兴Java使用类型擦除,但知道它至少有反射,这一事实再次让我振奋起来:D现在Java 8中的lambdas语言真的在跟上现代开发的速度。现在唯一缺少的是对getter和setter的本地支持,或者C中已知的属性。这不是一个公平的1。Henrik可能并不提倡挤压异常,也没有为它们写任何东西,因为他只是试图展示反射。另外一个是展示一些潜在的异常。如果我写了这个,它会是。。。卡奇{…我得到的变量可能尚未为method.invokeobj,arg1,arg2,…;中的方法初始化。method=null;解决了这个问题,但在答案中提到它并不是一个坏主意。@DeaMon1 Java方法不使用退出代码,但如果该方法返回任何东西,invoke将返回它返回的任何东西。如果运行method时出现异常,invoke将返回它返回的任何东西od,异常将被包装在InvocationTargetException中。我不同意。编写这样的代码以确保安全非常容易,我已经用多种语言编写了这样的代码。例如,可以创建一组允许的方法,并且只允许在名称在集合中的情况下调用方法。更安全但更简单的方法是limiting将每个允许的方法设置为特定状态,并且不允许调用该方法,除非线程/接口/用户/任何符合此类标准的对象。对于此类问题,请不要对调用进行分类。现在,我正在创建一个简单的程序,允许用户使用web界面在任意对象上定义任意任务。我知道这确实是不安全的,但一旦收到配置,就会执行适当的测试,它允许非程序员轻松地配置任务,并使程序能够将自定义类链接到我使用反射的部分的通用代码,以便允许它们通过web界面配置要使用的方法,而无需更新GUI.这里的最佳答案。完整而简洁。正确的最佳答案。你从哪里获得方法对象?从reflect pkg。到未来的读者;如果你关心性能,你会想在任何时候都使用invokeExact。为此,调用站点签名必须与方法句柄类型完全匹配。通常需要一些小修补才能开始工作。在本例中,您需要使用:methodHandle=methodHandle.asTypemethodHandle.type.changeParameterType0,Object.class;强制转换第一个参数,然后像String result=String methodHandle.invokeExactobj;Object这样调用,对象应该至少有个值。这对于我所需要的非常有效。我有一个已经实例化了nd只需要从中获取一个方法。在这里为异常添加捕获是一个好主意,但在其他方面,这对我来说非常有效。我认为我避免null异常的方法是使用nullables,但我使用的方法名称范围非常有限,实际上只是一个从1到4的计数器。这不是Java中比较字符串的方式。你可以st使用.equals方法。否则,您只是比较它们是否是相同的对象引用,而实际上您并不关心对象引用-只是字符串内容是否匹配。您也可以通过反射按名称获取方法,因此不确定为什么要滚动自己的方法?如果someVariable确实是对象,请调用someVariable.getClass。此外,不能使用类作为唯一参数调用getMethod。也不能使用方法调用方法。正确:someVariable.getClass.getMethodcoolMethod,ParameterClass.invokearguments;这种技术似乎比反射好得多。它真的好得多吗?@DimitriKopriwa索引是使用ram而不是CPU计算的方法。例如:整数索引,算法的难度是O1。这应该是答案。非常干净的解决方案。我需要从json配置文件中读取方法名称。因此使用此技术,我可能只使用HashMap而不是反射。
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);
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]
class Student{
int rollno;
String name;
void m1(int x,int y){
System.out.println("add is" +(x+y));
}
private void m3(String name){
this.name=name;
System.out.println("danger yappa:"+name);
}
void m4(){
System.out.println("This is m4");
}
}
import java.lang.reflect.Method;
public class StudentTest{
public static void main(String[] args){
try{
Class cls=Student.class;
Student s=(Student)cls.newInstance();
String x="kichha";
Method mm3=cls.getDeclaredMethod("m3",String.class);
mm3.setAccessible(true);
mm3.invoke(s,x);
Method mm1=cls.getDeclaredMethod("m1",int.class,int.class);
mm1.invoke(s,10,20);
}
catch(Exception e){
e.printStackTrace();
}
}
}
public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
object.getClass().getDeclaredMethod(methodName).invoke(object);
}
public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
}
package practice;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
public class MethodInvoke {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
String methodName1 = "methodA";
String methodName2 = "methodB";
MethodInvoke object = new MethodInvoke();
callMethodByName(object, methodName1);
callMethodByName(object, methodName2, 1, "Test");
}
public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
object.getClass().getDeclaredMethod(methodName).invoke(object);
}
public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
}
void methodA() {
System.out.println("Method A");
}
void methodB(int i, String s) {
System.out.println("Method B: "+"\n\tParam1 - "+i+"\n\tParam 2 - "+s);
}
}
Method A
Method B:
Param1 - 1
Param 2 - Test
@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);
}
}
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);
}
}
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);
}
}
class Person {
public void method1() {
try {
Method m2 = this.getClass().getDeclaredMethod("method2");
m1.invoke(this);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public void method2() {
// Do something
}
}