Рубрики
Без рубрики

Методы вызова во время выполнения с использованием отражения Java

Быстрое и практичное руководство по вызову метода выполнения с помощью API Java Reflection.

Автор оригинала: baeldung.

Методы вызова во время выполнения с использованием отражения Java

1. Обзор

В этой короткой статье мы кратко посмотрим, как вызвать методы во время выполнения с помощью API отражения Java .

2. Готовься

Давайте создадим простой класс, который мы будем использовать для примеров, которые следуют:

public class Operations {
    public double publicSum(int a, double b) {
        return a + b;
    }

    public static double publicStaticMultiply(float a, long b) {
        return a * b;
    }

    private boolean privateAnd(boolean a, boolean b) {
        return a && b;
    }

    protected int protectedMax(int a, int b) {
        return a > b ? a : b;
    }
}

3. Получение объекта метода

Во-первых, мы должны получить Метод объект, отражающий метод, который мы хотим вызвать. Класс объект, представляющий тип, в котором определяется метод, предоставляет два способа сделать это.

3.1. getMethod()

Мы можем использовать getMethod () найти какой-либо общедоступный метод, будь то статический или экземпляр, который определяется в классе или любом из его суперклассов.

Он получает название метода в качестве первого аргумента, за которым следуют типы аргументов метода:

Method sumInstanceMethod
  = Operations.class.getMethod("publicSum", int.class, double.class);

Method multiplyStaticMethod
  = Operations.class.getMethod(
    "publicStaticMultiply", float.class, long.class);

3.2. getDeclaredMethod()

Мы можем использовать getDeclaredMethod () для определения любого метода в классе. Это включает в себя общедоступные, защищенные, доступ по умолчанию и даже частные методы, но исключает унаследованные.

Он получает те же параметры, что и getMethod () :

Method andPrivateMethod
  = Operations.class.getDeclaredMethod(
    "privateAnd", boolean.class, boolean.class);
Method maxProtectedMethod
  = Operations.class.getDeclaredMethod("protectedMax", int.class, int.class);

4. Методы вызова

С Метод например, теперь мы можем позвонить вызвать () выполнить базовый метод и получить возвращенный объект.

4.1. Методы экземпляра

Чтобы вызвать метод экземпляра, первый аргумент, чтобы вызвать () должно быть примером Метод который отражает метод, на который ссылаются:

@Test
public void givenObject_whenInvokePublicMethod_thenCorrect() {
    Method sumInstanceMethod
      = Operations.class.getMethod("publicSum", int.class, double.class);

    Operations operationsInstance = new Operations();
    Double result
      = (Double) sumInstanceMethod.invoke(operationsInstance, 1, 3);

    assertThat(result, equalTo(4.0));
}

4.2. Статические методы

Поскольку эти методы не требуют, чтобы был вызван экземпляр, мы можем нулевой в качестве первого аргумента:

@Test
public void givenObject_whenInvokeStaticMethod_thenCorrect() {
    Method multiplyStaticMethod
      = Operations.class.getDeclaredMethod(
        "publicStaticMultiply", float.class, long.class);

    Double result
      = (Double) multiplyStaticMethod.invoke(null, 3.5f, 2);

    assertThat(result, equalTo(7.0));
}

5. Доступность метода

По умолчанию не все отраженные методы доступные . Это означает, что JVM обеспечивает проверку управления доступом при их вызове.

Например, если мы попытаемся вызвать частный метод за пределами его определяющего класса или защищенный метод из-за пределов подкласса или пакета его класса, мы получим НезаконныеАцессЭксцепция :

@Test(expected = IllegalAccessException.class)
public void givenObject_whenInvokePrivateMethod_thenFail() {
    Method andPrivateMethod
      = Operations.class.getDeclaredMethod(
        "privateAnd", boolean.class, boolean.class);

    Operations operationsInstance = new Operations();
    Boolean result
      = (Boolean) andPrivateMethod.invoke(operationsInstance, true, false);

    assertFalse(result);
}

@Test(expected = IllegalAccessException.class)
public void givenObject_whenInvokeProtectedMethod_thenFail() {
    Method maxProtectedMethod
      = Operations.class.getDeclaredMethod(
        "protectedMax", int.class, int.class);

    Operations operationsInstance = new Operations();
    Integer result
      = (Integer) maxProtectedMethod.invoke(operationsInstance, 2, 4);
    
    assertThat(result, equalTo(4));
}

Позвонив наборОсявный (истинный) на объекте отраженного метода СПМ подавляет проверку управления доступом и позволяет нам ссылаться на метод, не бросая исключение:

@Test
public void givenObject_whenInvokePrivateMethod_thenCorrect() {
    // ...
    andPrivateMethod.setAccessible(true);
    // ...
    Boolean result
      = (Boolean) andPrivateMethod.invoke(operationsInstance, true, false);

    assertFalse(result);
}

@Test
public void givenObject_whenInvokeProtectedMethod_thenCorrect() {
    // ...
    maxProtectedMethod.setAccessible(true);
    // ...
    Integer result
      = (Integer) maxProtectedMethod.invoke(operationsInstance, 2, 4);

    assertThat(result, equalTo(4));
}

6. Заключение

В этой быстрой статье мы видели, как вызвать экземпляр и статические методы класса во время выполнения через отражение. Мы также показали, как изменить доступный флаг на отраженных объектах метода для подавления проверок управления доступом Java при вызове частных и защищенных методов.

Как всегда, пример кода можно найти более на Github .