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

684

Wenn ich zwei Variablen habe:

Object obj;
String methodName = "getName";

objWie kann ich die durch identifizierte Klasse aufrufen, ohne die Klasse von zu kennen ?methodName zu kennen?

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

Brasskazoo
quelle
3
Verwenden Sie entweder die Reflection-API oder Groovy
Peter Kelley

Antworten:

972

Codierung von der Hüfte aus wäre so etwas wie:

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

Die Parameter geben die sehr spezifische Methode an, die Sie benötigen (wenn mehrere überladene Methoden verfügbar sind und die Methode keine Argumente enthält, geben Sie nur an methodName).

Dann rufen Sie diese Methode durch Aufrufen auf

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

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

Henrik Paul
quelle
2
War ein wenig verärgert über die Tatsache, dass Java Typlöschung verwendet, aber zu wissen, dass es zumindest Reflection hat, macht mich wieder munter: D Und jetzt mit Lambdas in Java 8 wird die Sprache mit der modernen Entwicklung wirklich auf dem neuesten Stand. Jetzt fehlt nur noch die native Unterstützung für Getter und Setter oder Eigenschaften, wie sie in C # bekannt sind.
7hi4g0
120
Keine faire -1. Henrik befürwortet wahrscheinlich keine Squashing-Ausnahmen und hat nichts für sie geschrieben, weil er nur versucht, Reflexion zu demonstrieren.
Unentschieden
70
Plus eins für einige mögliche Ausnahmen. Wenn ich das geschrieben hätte, wäre es ... catch (Ausnahme e) {...
mikbanUtah
1
Ich habe für die „Variable kann nicht initialisiert wurde“ methodin method.invoke(obj, arg1, arg2,...);. a method = null;löst das Problem, aber es ist keine schlechte Idee, es in der Antwort zu erwähnen.
Amin
2
@ DeaMon1 Java-Methoden verwenden keine "Exit-Codes", aber wenn die Methode etwas zurückgibt, invokewird alles zurückgegeben, was sie zurückgegeben hat. Wenn beim Ausführen der Methode eine Ausnahme auftritt, wird die Ausnahme in eine eingeschlossen InvocationTargetException.
ThePyroEagle
194

Verwenden Sie den Methodenaufruf aus der Reflexion:

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

Wo:

  • "class name" ist der Name der Klasse
  • objectToInvokeOn ist vom Typ Objekt 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
  • parameterTypesist vom Typ Class[]und deklariert die Parameter, die die Methode verwendet
  • paramsist vom Typ Object[]und deklariert die Parameter, die an die Methode übergeben werden sollen
Owen
quelle
Cool, ich denke du hast Recht mit getDeclaredMethod (), es ist wahrscheinlich 'sicherer' als getMethod () ..
brasskazoo
22
Falsch. Ja, getDeclaredMethod funktioniert mit privaten und geschützten Methoden. ABER: Es funktioniert nicht mit Methoden, die in Oberklassen definiert sind (geerbte Methoden). Es hängt also stark davon ab, was Sie tun möchten. In vielen Fällen soll es funktionieren, unabhängig von der genauen Klasse, in der die Methode definiert ist.
Jrudolph
Und wo soll ich "Klasse" -Datei ablegen? Erklären Sie vorzugsweise für Eclipse IDE
Dr.jacky
@ Mr.Hyde auf dem Klassenpfad.
Stijn de Witt
Was soll ich in und method.invoke () einfügen, wenn die von mir aufgerufene Methode überhaupt keine Parameter akzeptiert? Es scheint, dass ich noch einen zweiten Parameter angeben muss, sollte es ein leeres Objektarray sein?
Igor
101

Für diejenigen, die ein einfaches Codebeispiel in Java 7 wünschen:

Dog Klasse:

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

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 folgenden Parametern 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, ...);

Empfohlene Lektüre: Erstellen neuer Klasseninstanzen

Silber
quelle
1
Die beste Antwort hier. Vollständig und prägnant
Reuben JaMes Aveño Gruta
1
Richtige Beste Antwort.
Dhara Patel
Woher bekommst du MethodObjekt?
Parlad
Aus dem Reflexionspaket.
Silber
55

Die Methode kann so aufgerufen werden. Es gibt auch mehr Möglichkeiten (überprüfen Sie die Reflection-API), aber dies 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);
    }



}
Petr Macek
quelle
7
+1 für die einzige Antwort, bei der erkannt wurde, dass das OP in seiner Frage "keine Parameter" angegeben hat (und weil es auch das war, wonach ich gesucht habe).
John Fitzpatrick
16

Erstens nicht. Vermeiden Sie diese Art von Code. Es ist in der Regel sehr schlechter Code und auch unsicher (siehe Abschnitt 6 der Richtlinien für sichere Codierung für die Java-Programmiersprache, Version 2.0 ).

Wenn Sie es tun müssen, ziehen Sie java.beans der Reflexion vor. Bohnen umhüllen die Reflexion und ermöglichen einen relativ sicheren und konventionellen Zugang.

Tom Hawtin - Tackline
quelle
11
Ich stimme dir nicht zu. Es ist sehr einfach, solchen Code sicher zu schreiben, und ich habe dies in mehreren Sprachen getan. Beispielsweise könnte man eine Reihe zulässiger Methoden erstellen und nur zulassen, dass eine Methode aufgerufen wird, wenn sich ihr Name in der Menge befindet. Noch sicherer (und dennoch einfach) wäre es, jede erlaubte Methode auf einen bestimmten Zustand zu beschränken und nicht zuzulassen, dass die Methode aufgerufen wird, es sei denn, der Thread / die Schnittstelle / der Benutzer / was auch immer entspricht solchen Kriterien.
JSON
Seien Sie niemals so kategorisch in Bezug auf solche Themen. Im Moment erstelle ich ein einfaches Programm, mit dem der Benutzer beliebige Aufgaben über beliebige Objekte mithilfe von Webschnittstellen definieren kann. Ich weiß, dass es in der Tat unsicher ist, aber sobald die Konfiguration empfangen wurde, werden ordnungsgemäße Tests durchgeführt, und es ermöglicht einem Nicht-Programmierer, die Aufgaben einfach zu konfigurieren, und es gibt Programmen die Möglichkeit, benutzerdefinierte Klassen mit dem generischen Code zu verknüpfen (das ist der Teil Ich benutze Reflection, um ihnen zu ermöglichen, zu konfigurieren, welche Methoden über die Webschnittstelle verwendet werden sollen), ohne die GUI aktualisieren zu müssen.
DGoiko
14

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

  • statische oder Instanzaufrufe (in einem Fall benötigen Sie keine Instanz der Klasse, im anderen Fall müssen Sie sich möglicherweise auf einen vorhandenen Standardkonstruktor verlassen , der möglicherweise vorhanden ist oder nicht).
  • ö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 zufrieden )
  • Kapselung in eine weitere verwaltbare anwendbare Ausnahme, wenn Sie die zahlreichen Ausnahmen des Java-Systems zurückwerfen 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. <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;
}
VonC
quelle
12
Object obj;

Method method = obj.getClass().getMethod("methodName", null);

method.invoke(obj, null);
Hühnchen-Keks
quelle
Objekt sollte mindestens Wert / Werte haben.
Lova Chittumuri
Das hat wirklich gut funktioniert für das, was ich brauchte. Ich hatte eine Klasse, die bereits instanziiert war und nur eine Methode daraus machen musste. Das Hinzufügen von Fängen für Ausnahmen ist hier eine gute Idee, aber ansonsten hat dies für mich perfekt funktioniert. Ich denke, meine Art, Null-Ausnahmen zu vermeiden, bestand darin, Nullables zu verwenden, aber ich habe einen sehr eingeschränkten Bereich von Methodennamen verwendet (buchstäblich nur einen Zähler von 1 bis 4).
Jain Waldrip
12
//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");
Anujin
quelle
8

Wenn Sie den Aufruf mehrmals ausführen, können Sie die in Java 7 eingeführten neuen Methodenhandles verwenden. Hier geht es um Ihre Methode, die einen String zurückgibt:

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]
Christian Ullenboom
quelle
1
An zukünftige Leser; Wenn Sie Wert auf Leistung legen, invokeExactmöchten Sie diese verwenden, wann immer Sie können. Dafür muss die Signatur der Aufrufsite jedoch genau mit dem Typ des Methodenhandles übereinstimmen. Normalerweise muss man ein wenig basteln, um zur Arbeit zu kommen. In diesem Fall müssten Sie den ersten Parameter mit: methodHandle = methodHandle.asType(methodHandle.type().changeParameterType(0, Object.class));String result = (String) methodHandle.invokeExact(obj);
umwandeln
7

Dies klingt nach etwas, das mit dem Java Reflection-Paket machbar ist.

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

Insbesondere unter Aufrufen von Methoden nach Namen:

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);
     }
  }
}
zxcv
quelle
6

Indizierung (schneller)

Sie können FunctionalInterfaceMethoden in einem Container speichern, um sie zu indizieren. Sie können den Array-Container verwenden, um sie über Zahlen aufzurufen, oder die Hashmap, um sie über Zeichenfolgen aufzurufen. Mit diesem Trick können Sie Ihre Methoden indizieren, um sie dynamisch schneller aufzurufen .

@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(aNumber);
    }
}

Lambda-Syntax

Sie können auch die Lambda-Syntax verwenden:

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(aNumber);
    }
}
Amir Fo
quelle
1
Diese Technik scheint viel besser als Reflexion.
John O
Ist es wirklich viel besser?
Dimitri Kopriwa
@DimitriKopriwa Indizierung ist die Art und Weise, wie Sie RAM anstelle von CPU-Berechnungen verwenden. Für die Ganzzahlindizierung ist die Schwierigkeit des Algorithmus O(1).
Amir Fo
5
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);

SomeClassist die Klasse und someVariableist eine Variable.

Subrahmanya Prasad
quelle
Wenn someVariable wirklich ein Objekt ist, rufen Sie someVariable.getClass () auf. Sie können getMethod () auch nicht mit einer Klasse als einzigem Argument aufrufen. Weder Methode mit Methode aufrufen. Richtig: someVariable.getClass (). GetMethod ("coolMethod", parameterClasses) .invoke (Argumente);
Orangle
5

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();
}
Marcel
quelle
5

Der folgende 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<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());
    }
}

Vielen Dank....

Rahul Karankal
quelle
So vergleichen Sie Strings nicht in Java. Sie müssen die Methode .equals verwenden. Andernfalls vergleichen Sie nur, dass es sich um dieselbe Objektreferenz handelt, und Sie interessieren sich nicht für Objektreferenzen - nur der Zeichenfolgeninhalt stimmt überein. Sie können die Methode auch über Reflektion namentlich abrufen. Sie sind sich also nicht sicher, warum Sie Ihre eigene würfeln würden?
Lo-Tan
5

Hier sind die BEREITSCHUTZMETHODEN:

So rufen Sie eine Methode ohne Argumente auf:

public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    object.getClass().getDeclaredMethod(methodName).invoke(object);
}

So rufen Sie eine Methode mit Argumenten auf:

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

Verwenden Sie die oben genannten Methoden wie folgt:

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

Ausgabe:

Methode A.  
Methode B:  
	Param1 - 1  
	Parameter 2 - Test
Sandeep Nalla
quelle
3

Student.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();
        }
     }
}
user8387971
quelle
1

Sie sollten Reflection verwenden - ein Klassenobjekt und dann eine Methode in dieser Klasse initiieren und diese Methode dann für ein Objekt mit optionalen Parametern aufrufen . Denken Sie daran, das folgende Snippet in den Try-Catch- Block zu packen

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);
Detman
quelle
1

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.

Laxman G.
quelle
1

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 so benutzt du es:

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

Mit jooR ist es nur:

on(obj).call(methodName /*params*/).get()

Hier ist ein ausführlicheres Beispiel:

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

Dies druckt:

3, 12, 1

Andronicus
quelle
-10

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

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

Wenn Sie dann die Methode aufrufen müssen, geben Sie einfach so etwas ein

//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()); 
SMayne
quelle
4
Wenn die Instanz bereits während der Kompilierungszeit bekannt ist, warum tun Sie das nicht einfach className.getName().toString()? Sie vermissen den ganzen Reflexionspunkt.
BalusC
Wie gesagt, in diesem Fall unnötig, aber vorausgesetzt, Sie wissen immer, dass die Instanz eine schlechte Programmiergewohnheit ist.
SMayne
2
@SMayne: Ich würde vorschlagen, diesen Beitrag zu löschen.
lpapp
schlechte programmierung wäre in diesem
fall