Wie rufe ich eine Java-Methode auf, wenn der Methodenname als Zeichenfolge angegeben wird?

Wenn ich zwei Variablen habe:

Object obj; String methodName = "getName"; 

Wie kann ich, ohne die class von obj , die Methode aufrufen, die durch methodName identifiziert wurde?

Die aufgerufene Methode hat keine Parameter und einen String Rückgabewert. Es ist ein Getter für eine Java-Bean .

Codierung von der Hüfte, wäre es etwa so:

 java.lang.reflect.Method method; try { method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..); } catch (SecurityException e) { ... } catch (NoSuchMethodException e) { ... } 

Die Parameter identifizieren die sehr spezifische Methode, die Sie benötigen (wenn mehrere überladen verfügbar sind, wenn die Methode keine Argumente hat, geben Sie methodName ).

Dann rufen Sie diese Methode durch Aufruf auf

 try { method.invoke(obj, arg1, arg2,...); } catch (IllegalArgumentException e) { ... } catch (IllegalAccessException e) { ... } catch (InvocationTargetException e) { ... } 

Lassen Sie die Argumente in .invoke , wenn Sie keine haben. Aber ja. Lesen Sie mehr über Java Reflection

Verwenden Sie den Methodenaufruf aus der Reflektion:

 Class< ?> c = Class.forName("class name"); Method method = c.getDeclaredMethod("method name", parameterTypes); method.invoke(objectToInvokeOn, params); 

Woher:

  • "class name" ist der Name der class
  • objectToInvokeOn ist vom Typ Object und ist das Objekt, für das Sie die Methode aufrufen möchten
  • "method name" ist der Name der Methode, die Sie aufrufen möchten
  • parameterTypes hat den Typ Class[] und deklariert die Parameter der Methode
  • params ist vom Typ Object[] und deklariert die Parameter, die an die Methode übergeben werden sollen

Für diejenigen, die ein geradliniges Codebeispiel in Java 7 möchten:

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 class:

 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 } } 

Ausgabe: Mishka is 3 year(s) old.


Sie können den Konstruktor mit Parametern auf diese Weise aufrufen:

 Constructor< ?> dogConstructor = dogClass.getConstructor(String.class, int.class); Object dog = dogConstructor.newInstance("Hachiko", 10); 

Alternativ können Sie entfernen

 String dogClassName = "com.mypackage.bean.Dog"; Class< ?> dogClass = Class.forName(dogClassName); Object dog = dogClass.newInstance(); 

und TU

 Dog dog = new Dog(); Method method = Dog.class.getMethod(methodName, ...); method.invoke(dog, ...); 

Vorgeschlagener Messwert: Erstellen neuer classninstanzen

Die Methode kann so aufgerufen werden. Es gibt auch mehr Möglichkeiten (überprüfen Sie die reflection API), aber das ist die einfachste:

 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); } } 

Erstens, nicht. Vermeiden Sie diese Art von Code. Es tendiert dazu, wirklich schlechter Code zu sein und unsicher zu sein (siehe Abschnitt 6 der Secure Coding Guidelines für die Java-Programmiersprache, Version 2.0 ).

Wenn Sie es tun müssen, bevorzugen Sie java.beans zur reflection. Bohnen umhüllen reflection, die verhältnismäßig sicheren und herkömmlichen Zugang erlaubt.

Um die Antworten meines Kollegen zu vervollständigen, sollten Sie Folgendes beachten:

  • Static- oder Instanzaufrufe (in einem Fall benötigen Sie keine Instanz der class, in der anderen müssen Sie möglicherweise auf einen vorhandenen Standardkonstruktor zurückgreifen, der möglicherweise nicht vorhanden ist.)
  • Öffentlicher oder nicht-öffentlicher Methodenaufruf (für Letzteres müssen Sie setAccessible für die Methode in einem doPrivileged-Block aufrufen , andere Findbugs sind nicht glücklich )
  • Einkapselung in eine verwaltbare anwendbare Ausnahme, wenn Sie die zahlreichen Java-Systemausnahmen zurückcasting möchten (daher die CCException im folgenden Code)

Hier ist ein alter Java1.4-Code, der diese Punkte berücksichtigt:

 /** * Allow for instance call, avoiding certain class circular dependencies. 
* 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"); 
 Object obj; Method method = obj.getClass().getMethod("methodName", null); method.invoke(obj, null); 

Dies klingt nach etwas, das mit dem Java Reflection-Paket möglich ist.

http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html

Insbesondere unter Aufrufen von Methoden nach Name:

import java.lang.reflekt. *;

 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); } } } 

Wenn Sie den Aufruf mehrere Male ausführen, können Sie die neuen Methoden-Handles verwenden, die in Java 7 eingeführt wurden. Hier gehen wir zur Methode, die einen String zurückgibt:

 Object obj = new Point( 100, 200 ); String methodName = "toString"; Class 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 ist die class und someVariable ist eine Variable.

Bitte beachten Sie folgenden Code kann Ihnen helfen.

 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 

Vielen Dank....

Schüler.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(); } } } 

Ich mache das so:

 try { YourClass yourClass = new YourClass(); Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class); method.invoke(yourClass, parameter); } catch (Exception e) { e.printStackTrace(); } 

Sie sollten reflection verwenden – initialisieren Sie ein classnobjekt, dann eine Methode in dieser class und rufen Sie dann diese Methode für ein Objekt mit optionalen Parametern auf. Denken Sie daran, das folgende Snippet in den try-catch- Block zu schreiben

Ich hoffe es hilft!

 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); 

Das funktioniert gut für mich:

 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); } 

}

Ausgabe:

My input testparam

Ich kann die Methode aufrufen, indem ich ihren Namen an eine andere Methode (wie main) übergebe.

mit 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); } 

und hier ist, wie Sie es verwenden:

 String className = "com.example.helloworld"; String methodName = "print"; Class< ?>[] argsTypes = {String.class, String.class}; Object[] methArgs = { "hello", "world" }; launchProcess(className, methodName, argsTypes, methArgs); 

Für mich wäre ein ziemlich einfacher und narrensicherer Weg, einfach eine Methodenaufrufmethode wie folgt zu machen:

 public static object methodCaller(String methodName) { if(methodName.equals("getName")) return className.getName(); } 

dann, wenn Sie die Methode aufrufen müssen, setzen Sie einfach so etwas

 //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());