7

Как вызвать метод Java по имени, представленному в виде строки?

1

У меня есть две переменные:

Object obj;
String methodName = "getName";

Как я могу вызвать метод, указанный в переменной methodName, на объекте obj, не зная при этом класс obj?

Метод, который я хочу вызвать, не принимает параметров и возвращает значение типа String. Это геттер для Java bean.

5 ответ(ов)

0

Метод можно вызвать следующим образом. Также существует множество других возможностей (посмотрите API рефлексии), но это самый простой способ:

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 = "Некоторый объект";

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

}

В этом примере мы используем рефлексию для получения метода length класса String, а затем вызываем этот метод на объекте valueObject. Результат выполнения метода должен равняться 11, что соответствует длине строки "Некоторый объект".

0

Сначала, не стоит так делать. Избегайте подобного кода. Он часто оказывается плохим и небезопасным (см. раздел 6 Руководства по безопасному программированию для языка Java, версия 2.0).

Если вам все же необходимо это сделать, предпочтите использование java.beans вместо рефлексии. Beans оборачивает рефлексию, обеспечивая относительно безопасный и стандартный доступ.

0

Индексация (ускорение)

Вы можете использовать FunctionalInterface для хранения методов в контейнере и их индексации. Можно использовать массив для вызова методов по индексу или hashmap для вызова по строковым ключам. С помощью этого подхода вы можете индексировать ваши методы, чтобы вызывать их динамически быстрее.

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

Синтаксис лямбд

Вы также можете использовать синтаксис лямбд:

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

Этот подход позволяет вам легко добавлять новые методы для вычисления площадей различных фигур и выполнять их по индексу без дополнительных затрат на условия или явные вызовы.

0

В коде, который вы привели, происходит вызов метода methodName у объекта obj с использованием рефлексии в Java. Давайте разберем его по шагам:

  1. Объявление объекта:

    Object obj;
    

    Здесь создается переменная obj типа Object. Пожалуйста, убедитесь, что этот объект инициализирован перед его использованием.

  2. Получение метода по имени:

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

    В этой строке мы получаем объект Method, который представляет метод methodName класса объекта obj. Обратите внимание, что второй параметр (null) указывает, что метод не принимает аргументов. Если вашим методом есть параметры, вам нужно будет указать их типы в виде массива классов.

  3. Вызов метода:

    method.invoke(obj, null);
    

    Здесь мы вызываем метод methodName на объекте obj. Аргумент null во втором параметре invoke означает, что метод не принимает аргументов.

Если у вас возникнут дополнительные вопросы по использованию рефлексии в Java или по какому-либо другому аспекту, не стесняйтесь задавать!

0

Для выполнения динамического вызова метода класса по его имени в Java, вы можете использовать следующий код:

// Шаг 1 - Используем строку funClass для получения объекта класса
String funClass = "package.myclass";
Class<?> c = Class.forName(funClass);

// Шаг 2 - Создаем экземпляр объекта указанного класса
Object o = c.newInstance();

// Подготавливаем массив аргументов, которые принимает ваша функция, в данном случае только одну строку
Class<?>[] paramTypes = new Class[1];
paramTypes[0] = String.class;
String methodName = "mymethod";

// Получаем объект метода по имени метода и типам параметров
Method m = c.getDeclaredMethod(methodName, paramTypes);

// Вызываем метод с фактическими параметрами
m.invoke(o, "testparam");

Этот код сначала загружает класс по его имени (в строке funClass), создает его экземпляр, находит метод с заданным именем и типами параметров, а затем вызывает этот метод с указанными аргументами. Убедитесь, что вы обрабатываете возможные исключения, такие как ClassNotFoundException, InstantiationException, IllegalAccessException и InvocationTargetException для надежного кода.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь