782 Stimmen

Wie rufe ich eine Java-Methode auf, wenn der Name der Methode als String angegeben ist?

Wenn ich zwei Variablen habe:

Object obj;
String methodName = "getName";

Ohne Kenntnis der Klasse der obj wie kann ich die Methode aufrufen, die durch methodName darauf?

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

1082voto

Henrik Paul Punkte 65301

Aus der Hüfte heraus kodiert, würde es etwa so aussehen:

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 spezifische Methode, die Sie benötigen (wenn mehrere überladene Methoden verfügbar sind, wenn die Methode keine Argumente hat, geben Sie nur methodName ).

Dann rufen Sie diese Methode auf, indem Sie

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

Auch hier lassen Sie die Argumente in .invoke , wenn Sie keine haben. Aber ja. Lesen Sie über Java-Reflexion

236voto

Owen Punkte 2641

Utilice 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 Object und ist das Objekt, für das die Methode aufgerufen werden soll
  • "method name" ist der Name der Methode, die Sie aufrufen wollen
  • parameterTypes ist vom Typ Class[] und deklariert die Parameter, die die Methode benötigt
  • params ist vom Typ Object[] und deklariert die Parameter, die an die Methode übergeben werden sollen

132voto

silver Punkte 4971

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

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

Sortie : Mishka is 3 year(s) old.


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

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

Alternativ können Sie auch die

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

und tun

Dog dog = new Dog();

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

Empfohlene Lektüre: Neue Klasseninstanzen erstellen

55voto

Petr Macek Punkte 1503

Die Methode kann auf diese Weise aufgerufen werden. Es gibt noch weitere Möglichkeiten (siehe 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);
    }

}

16voto

Amir Fo Punkte 3901

Indizierung (schneller)

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

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

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X