webentwicklung-frage-antwort-db.com.de

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 die mit obj gekennzeichnete Methode aufrufen, ohne die Klasse von methodName zu kennen?

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

642
brasskazoo

Codierung aus der Hüfte, wäre es 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, wenn die Methode keine Argumente enthält, geben Sie nur methodName an).

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 auch hier die Argumente in .invoke weg, falls Sie keine haben. Aber ja. Lesen Sie mehr über Java Reflection

923
Henrik Paul

Verwenden Sie Methodenaufruf from reflection:

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 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 ist vom Typ Class[] und deklariert die Parameter, die die Methode annimmt
  • params ist vom Typ Object[] und deklariert die Parameter, die an die Methode übergeben werden sollen
179
Owen

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 folgendermaßen mit 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

88
silver

Die Methode kann folgendermaßen 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);
    }



}
55
Petr Macek

Zuerst nicht. Vermeiden Sie diese Art von Code. Es handelt sich in der Regel um einen sehr schlechten und unsicheren Code (siehe Abschnitt 6 von Richtlinien für die sichere Codierung der Programmiersprache Java, Version 2. ).

Wenn Sie dies tun müssen, ziehen Sie Java.beans der Reflektion vor. Beans Wraps Reflection ermöglichen einen relativ sicheren und konventionellen Zugang.

17

Um die Antworten meines Kollegen zu vervollständigen, möchten Sie vielleicht genau auf Folgendes achten:

  • statische Aufrufe oder Instanzaufrufe (in einem Fall benötigen Sie keine Instanz der Klasse, in einem anderen Fall müssen Sie möglicherweise auf einen vorhandenen Standardkonstruktor zurückgreifen. ) das kann oder kann nicht da sein)
  • öffentlicher oder nicht öffentlicher Methodenaufruf (für letzteren müssen Sie setAccessible für die Methode innerhalb eines doPrivileged-Blocks aufrufen, andere findbugs won) nicht glücklich sein )
  • zusammenfassung in eine weitere verwaltbare anwendbare Ausnahme, wenn Sie die zahlreichen Java Systemausnahmen 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;
}
13
VonC
//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");
12
anujin
Object obj;

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

method.invoke(obj, null);
12

Wenn Sie den Aufruf mehrmals ausführen, können Sie die neuen Methodenhandles verwenden, die in Java 7 eingeführt wurden. Hier ist die 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]
8

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

http://Java.Sun.com/developer/technicalArticles/ALT/Reflection/index.html

Insbesondere unter Methoden namentlich aufrufen:

java.lang.reflect. * importieren;

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

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

5
Rahul Karankal
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);

SomeClass ist die Klasse und someVariable ist eine Variable.

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

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();
        }
     }
}
3
user8387971

Hier sind die BEREIT, METHODEN ZU VERWENDEN:

m eine Methode ohne Argumente aufzurufen:

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

m eine Methode mit Argumenten aufzurufen:

    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 obigen 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: 
 Parameter1 - 1 
 Parameter 2 - Test
3
Sandeep Nalla

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

Sie sollten reflection - init als Klassenobjekt und dann als Methode in dieser Klasse verwenden und diese Methode dann für ein Objekt mit optional Parametern aufrufen. Denken Sie daran, das folgende Snippet in den Block try-catch 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);
1
nurxyz

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.

1
Laxman G