Как вызвать метод Java при задании имени метода в виде строки?
если у меня есть две переменные:
Object obj;
String methodName = "getName";
не зная класс obj
, Как я могу вызвать метод, выявленных methodName
на нем?
вызываемый метод не имеет параметров, а String
возвращаемое значение. Это геттер для Java bean.
18 ответов:
Кодирование от бедра, это было бы что-то вроде:
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
использовать вызов метода из размышлений:
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:
Dog
класс: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 } }
выход:
Mishka is 3 year(s) old.
вы можете вызвать конструктор с параметрами следующим образом:
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, ...);
рекомендуемое чтение: Создание Новых Экземпляров Класса
метод может быть вызван таким. Есть также больше возможностей (проверьте 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); } }
во-первых, не избегайте такого рода кода. Это, как правило, очень плохой код и небезопасно тоже (см. раздел 6 рекомендации по безопасному кодированию для Язык программирования Java, версия 2.0).
если вы должны это сделать, предпочитайте java.бобы к размышлению. Фасоль обертывает отражение, позволяя относительно безопасный и обычный доступ.
чтобы завершить ответы моего коллеги, вы можете обратить пристальное внимание на:
- статические или экземплярные вызовы (в одном случае вам не нужен экземпляр класса, в другом, возможно, вам придется полагаться на существующий конструктор по умолчанию это может быть или не быть там)
- публичный или непубличный вызов метода (для последнего,вам нужно вызвать setAccessible на метод в пределах doPrivileged блока, другие findbugs не будет будьте счастливы)
- инкапсулирование в еще одно управляемое прикладное исключение, если вы хотите отбросить многочисленные системные исключения 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; }
//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");
это звучит как что-то, что выполнимо с пакетом отражения Java.
http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html
в частности, под вызов методов по имени:
импорт java.ленг.отражать.*;
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 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]
Method method = someVariable.class.getMethod(SomeClass); String status = (String) method.invoke(method);
SomeClass
класс аsomeVariable
- это переменная.
пожалуйста, см. следующий код может помочь вам.
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()); } }
спасибо....
студент.java
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"); } }
StudentTest.java
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(); } } }
Я делаю это так:
try { YourClass yourClass = new YourClass(); Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class); method.invoke(yourClass, parameter); } catch (Exception e) { e.printStackTrace(); }
вы должны использовать 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); }
}
выход:
My input testparam
Я могу вызвать метод, передав его имя другому методу (например, main).
используя
import java.lang.reflect.*;
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); }
а вот как вы его используете:
String className = "com.example.helloworld"; String methodName = "print"; Class<?>[] argsTypes = {String.class, String.class}; Object[] methArgs = { "hello", "world" }; launchProcess(className, methodName, argsTypes, methArgs);
для меня довольно простой и дурацкий способ доказательства состоял бы в том, чтобы просто сделать метод вызывающего метода следующим образом:
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());