Методы вызова во время выполнения с использованием отражения 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 .