Comment appeler une méthode Java avec le nom de la méthode sous forme de chaîne?

Si j’ai deux variables:

Object obj; Ssortingng methodName = "getName"; 

Sans connaître la classe d’ obj , comment puis-je appeler la méthode identifiée par methodName ?

La méthode appelée n’a aucun paramètre et une valeur de retour de Ssortingng . C’est un getter pour un bean Java .

Codant de la hanche, ce serait quelque chose comme:

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

Les parameters identifient la méthode très spécifique dont vous avez besoin (s’il y a plusieurs surchargés disponibles, si la méthode n’a pas d’arguments, methodName uniquement methodName ).

Ensuite, vous invoquez cette méthode en appelant

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

Encore une fois, .invoke les arguments dans .invoke , si vous n’en avez pas. Mais ouais. Lisez à propos de Java Reflection

Utiliser l’ invocation de la méthode de reflection:

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

Où:

  • "class name" est le nom de la classe
  • objectToInvokeOn est de type Object et est l’object sur objectToInvokeOn vous souhaitez appeler la méthode
  • "method name" est le nom de la méthode que vous souhaitez appeler
  • parameterTypes est de type Class[] et déclare les parameters pris par la méthode
  • params est de type Object[] et déclare les parameters à transmettre à la méthode

Pour ceux qui veulent un exemple de code simple en Java 7:

Classe de Dog :

 package com.mypackage.bean; public class Dog { private Ssortingng name; private int age; public Dog() { // empty constructor } public Dog(Ssortingng name, int age) { this.name = name; this.age = age; } public Ssortingng getName() { return name; } public void setName(Ssortingng name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void printDog(Ssortingng name, int age) { System.out.println(name + " is " + age + " year(s) old."); } } 

Classe ReflectionDemo :

 package com.mypackage.demo; import java.lang.reflect.*; public class ReflectionDemo { public static void main(Ssortingng[] args) throws Exception { Ssortingng dogClassName = "com.mypackage.bean.Dog"; Class< ?> dogClass = Class.forName(dogClassName); // convert ssortingng classname to class Object dog = dogClass.newInstance(); // invoke empty constructor Ssortingng methodName = ""; // with single parameter, return void methodName = "setName"; Method setNameMethod = dog.getClass().getMethod(methodName, Ssortingng.class); setNameMethod.invoke(dog, "Mishka"); // pass arg // without parameters, return ssortingng methodName = "getName"; Method getNameMethod = dog.getClass().getMethod(methodName); Ssortingng name = (Ssortingng) getNameMethod.invoke(dog); // explicit cast // with multiple parameters methodName = "printDog"; Class< ?>[] paramTypes = {Ssortingng.class, int.class}; Method printDogMethod = dog.getClass().getMethod(methodName, paramTypes); printDogMethod.invoke(dog, name, 3); // pass args } } 

Production: Mishka is 3 year(s) old.


Vous pouvez appeler le constructeur avec des parameters de cette manière:

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

Vous pouvez également supprimer

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

et fait

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

Lectures suggérées: Création de nouvelles instances de classe

La méthode peut être appelée comme ceci. Il y a aussi plus de possibilités (vérifier l’api de reflection), mais c’est le plus simple:

 import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; public class ReflectionTest { private Ssortingng methodName = "length"; private Ssortingng 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); } } 

D’abord, ne le faites pas. Évitez ce genre de code. Ce code a tendance à être très mauvais et peu sûr (voir la section 6 des Directives de codage sécurisé pour Java Programming Language, version 2.0 ).

Si vous devez le faire, préférez java.beans à la reflection. Les haricots enveloppent la reflection permettant un access relativement sûr et conventionnel.

Pour compléter les réponses de mon collègue, vous voudrez peut-être porter une attention particulière à:

  • Appels statiques ou d’instance (dans un cas, vous n’avez pas besoin d’une instance de la classe, dans l’autre, vous devrez peut-être compter sur un constructeur par défaut existant qui peut ou non être présent)
  • appel de méthode publique ou non publique (pour ce dernier, vous devez appeler setAccessible sur la méthode dans un bloc doPrivileged , les autres findbugs ne seront pas satisfaits )
  • encapsuler dans une exception applicative plus gérable si vous voulez renvoyer les nombreuses exceptions du système Java (d’où la CCException dans le code ci-dessous)

Voici un ancien code java1.4 qui prend en compte ces points:

 /** * 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 Ssortingng classname, final Ssortingng 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[]{Ssortingng[].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+Ssortingng.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 ssortingng funClass to convert to class Ssortingng 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 ssortingng here Class[] paramTypes = new Class[1]; paramTypes[0]=Ssortingng.class; Ssortingng 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); 

Cela ressemble à quelque chose qui est faisable avec le package Java Reflection.

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

Particulièrement sous les méthodes d’invocation par nom:

import java.lang.reflect. *;

 public class method2 { public int add(int a, int b) { return a + b; } public static void main(Ssortingng 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); } } } 

Si vous faites l’appel plusieurs fois, vous pouvez utiliser les nouveaux descripteurs de méthode introduits dans Java 7. Pour votre méthode, retournez une chaîne:

 Object obj = new Point( 100, 200 ); Ssortingng methodName = "toSsortingng"; Class resultType = Ssortingng.class; MethodType mt = MethodType.methodType( resultType ); MethodHandle methodHandle = MethodHandles.lookup().findVirtual( obj.getClass(), methodName, mt ); Ssortingng result = resultType.cast( methodHandle.invoke( obj ) ); System.out.println( result ); // java.awt.Point[x=100,y=200] 
 Method method = someVariable.class.getMethod(SomeClass); Ssortingng status = (Ssortingng) method.invoke(method); 

SomeClass est la classe et someVariable est une variable.

S’il vous plaît se référer au code suivant peut vous aider.

 public static Method method[]; public static MethodClass obj; public static Ssortingng testMethod="A"; public static void main(Ssortingng args[]) { obj=new MethodClass(); method=obj.getClass().getMethods(); try { for(int i=0;i 

Merci....

Student.java

 class Student{ int rollno; Ssortingng name; void m1(int x,int y){ System.out.println("add is" +(x+y)); } private void m3(Ssortingng 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(Ssortingng[] args){ try{ Class cls=Student.class; Student s=(Student)cls.newInstance(); Ssortingng x="kichha"; Method mm3=cls.getDeclaredMethod("m3",Ssortingng.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(); } } } 

Je fais ça comme ça:

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

Vous devez utiliser la reflection – init un object de classe, puis une méthode dans cette classe, puis invoquer cette méthode sur un object avec des parameters facultatifs . N’oubliez pas d’envelopper l’extrait suivant dans le bloc try-catch

J’espère que cela aide!

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

Cela fonctionne très bien pour moi:

 public class MethodInvokerClass { public static void main(Ssortingng[] 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]=Ssortingng.class; Ssortingng methodName = "countWord"; Method m = c.getDeclaredMethod(methodName, paramTypes); m.invoke(o, "testparam"); } public void countWord(Ssortingng input){ System.out.println("My input "+input); } 

}

Sortie:

My input testparam

Je suis capable d’invoquer la méthode en passant son nom à une autre méthode (comme main).

en utilisant import java.lang.reflect.*;

 public static Object launchProcess(Ssortingng className, Ssortingng methodName, Class< ?>[] argsTypes, Object[] methodArgs) throws Exception { Class< ?> processClass = Class.forName(className); // convert ssortingng 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); } 

et voici comment vous l’utilisez:

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

pour moi, un moyen assez simple et infaillible serait de simplement créer une méthode d’appel de méthode comme ceci:

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

alors quand vous avez besoin d’appeler la méthode simplement mettre quelque chose comme ça

 //calling a toSsortingng method is unnessary here, but i use it to have my programs to both rigid and self-explanitory System.out.println(methodCaller(methodName).toSsortingng());