How do I invoke a Java method when given the method name as a string?
如果我有两个变量:
在不知道
正在调用的方法没有参数,返回值为
从臀部开始编码,它应该是这样的:
1 2 3 4 5 | java.lang.reflect.Method method; try { method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..); } catch (SecurityException e) { ... } catch (NoSuchMethodException e) { ... } |
参数标识您需要的非常具体的方法(如果有多个重载可用,如果该方法没有参数,则只提供
然后通过调用
1 2 3 4 5 | try { method.invoke(obj, arg1, arg2,...); } catch (IllegalArgumentException e) { ... } catch (IllegalAccessException e) { ... } catch (InvocationTargetException e) { ... } |
同样,如果你没有任何理由的话,把
使用反射的方法调用:
1 2 3 | Class<?> c = Class.forName("class name"); Method method = c.getDeclaredMethod("method name", parameterTypes); method.invoke(objectToInvokeOn, params); |
哪里:
"class name" 是类的名称。objectToInvokeOn 的类型为object,并且是要在其上调用方法的对象"method name" 是要调用的方法的名称parameterTypes 的类型为Class[] 并声明该方法采用的参数params 是Object[] 类型,并声明要传递给方法的参数
对于那些想要Java 7中直接代码示例的人:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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."); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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 } } |
输出:
您可以用以下方式调用带有参数的构造函数:
1 2 |
或者,您可以删除
1 2 3 |
并且做
1 2 3 4 |
建议阅读:创建新的类实例
可以这样调用方法。还有更多的可能性(检查反射API),但这是最简单的一个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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); } } |
首先,不要。避免使用这种代码。它往往是非常糟糕的代码和不安全的(参见安全编码指南第6节Java编程语言,第2版。
如果必须这样做,最好选择java.beans而不是reflection。beans包装反射,允许相对安全和常规的访问。.
要完成我同事的回答,您可能需要密切关注:
- 静态或实例调用(在一种情况下,您不需要类的实例,而在另一种情况下,您可能需要依赖可能存在或不存在的现有默认构造函数)
- 公共或非公共方法调用(对于后者,您需要在DoPrivileged块内的方法上调用setAccessible,其他findbugs将不高兴)
- 如果您想抛出大量Java系统异常(因此在下面的代码中有CcExchange),则封装成一个更易于管理的应用异常。
下面是一个老的java1.4代码,它考虑了以下几点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | /** * 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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //Step1 - Using string funClass to convert to class String funClass ="package.myclass"; Class c = Class.forName(funClass); //Step2 - instantiate an object of the class abov Object o = c.newInstance(); //Prepare array of the arguments that your function accepts, lets say only one string here Class[] paramTypes = new Class[1]; paramTypes[0]=String.class; String methodName ="mymethod"; //Instantiate an object of type method that returns you method name Method m = c.getDeclaredMethod(methodName, paramTypes); //invoke method with actual params m.invoke(o,"testparam"); |
1 2 3 4 5 |
如果您多次调用该调用,您可以使用Java 7中介绍的新方法句柄。下面我们将介绍返回字符串的方法:
1 2 3 4 5 6 7 8 9 | 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反射包所能做的事情。
http://java.sun.com/developer/technicalArticles/alt/reflection/index.html
尤其是在按名称调用方法下:
导入Java.Lang.ExpR.*;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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); } } } |
请参考以下代码可能对您有所帮助。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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()); } } |
谢谢。。。。
我这样做:
1 2 3 4 5 6 7 |
1 2 |
学生JAVA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
学生测试.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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(); } } } |
这对我来说很好:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); } |
}
输出:
我可以通过将方法的名称传递给另一个方法(如main)来调用该方法。
使用
1 2 3 4 5 6 7 8 9 10 | public static Object launchProcess(String className, String methodName, Class<?>[] argsTypes, Object[] methodArgs) throws Exception { Class<?> processClass = Class.forName(className); // convert string classname to class Object process = processClass.newInstance(); // invoke empty constructor Method aMethod = process.getClass().getMethod(methodName,argsTypes); Object res = aMethod.invoke(process, methodArgs); // pass arg return(res); } |
以下是您如何使用它:
1 2 3 4 5 |
您应该使用reflection-init一个类对象,然后使用这个类中的一个方法,然后使用可选参数对一个对象调用这个方法。记住在try catch块中包装以下代码段
希望它有帮助!
1 2 3 | 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); |
以下是现成的方法:
要调用不带参数的方法,请执行以下操作:
1 2 3 | public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { object.getClass().getDeclaredMethod(methodName).invoke(object); } |
要使用参数调用方法,请执行以下操作:
1 2 3 | 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); } |
使用上述方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | 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:"+" \tParam1 -"+i+" \tParam 2 -"+s); } } |
输出:
对于我来说,一个非常简单和简单的方法就是简单地生成这样的方法调用方方法:
1 2 3 4 5 | public static object methodCaller(String methodName) { if(methodName.equals("getName")) return className.getName(); } |
然后当你需要调用这个方法时,简单地把类似这样的东西
1 2 | //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()); |