Class.getDeclaredMethod: примеры (JAVA)
Class.getDeclaredMethod(String name, Class>... parameterTypes): MethodОписание и сигнатура
Метод Class.getDeclaredMethod используется для получения отражения метода, объявленного прямо в данном классе. Поиск производится только по методам, определенным в самой таблице класса, без учета унаследованных методов. Возвращается объект java.lang.reflect.Method, позволяющий получить информацию о сигнатуре метода и выполнить вызов через рефлексию.
public Method getDeclaredMethod(String name, Class>... parameterTypes)
throws NoSuchMethodException, SecurityException
Аргументы:
- name - имя метода в виде строки. При передаче
nullповедение приводит к исключению (см. секцию ошибок). - parameterTypes - список классов параметров в порядке объявления метода. Для метода без параметров передается пустой массив или ничего не передавать. Для varargs-метода указывается тип массива, например для
void f(String... s)-String[].class.
Возвращаемое значение:
- При успешном поиске возвращается экземпляр
Methodдля запрошенного метода. - При отсутствии соответствия выбрасывается
NoSuchMethodException. - При ограничениях политики безопасности может быть
SecurityException. При попытке доступа к недоступному методу в среде с модульной защитой может возникнутьInaccessibleObjectExceptionпри дальнейшем использованииsetAccessible(true)или вызове.
Особенности поведения:
- Метод возвращает объявленные в классе методы любого модификатора доступа: public, protected, package-private и private.
- Для получения унаследованных public-методов существует
Class.getMethod. - Для группового получения всех объявленных методов применяется
Class.getDeclaredMethods().
Короткие практические примеры
Примеры показывают получение и вызов методов с разными сигнатурами и обработку типичных результатов.
1) Получение и вызов public-метода без параметров
class Demo {
public void hello() { System.out.println("hello"); }
}
// получение
Method m = Demo.class.getDeclaredMethod("hello");
// вызов
m.invoke(new Demo());
hello
2) Получение private-метода с параметрами и получение результата
class Calc {
private int add(int a, int b) { return a + b; }
}
Method m = Calc.class.getDeclaredMethod("add", int.class, int.class);
m.setAccessible(true); // при разрешении доступа
int result = (int) m.invoke(new Calc(), 2, 3);
System.out.println(result);
5
3) Поиск varargs-метода (указывается тип массива)
class Joiner {
public String join(String... parts) { return String.join(",", parts); }
}
Method m = Joiner.class.getDeclaredMethod("join", String[].class);
String out = (String) m.invoke(new Joiner(), (Object) new String[]{"a","b"});
System.out.println(out);
a,b
4) Ошибка при неправильном имени или сигнатуре
// если такого метода нет
Demo.class.getDeclaredMethod("noSuch");
java.lang.NoSuchMethodException: Demo.noSuch()
Альтернативы в Java и особенности
Сравнение похожих API в Java:
- Class.getMethod - возвращает public-метод, включая унаследованные. Предпочтительнее при необходимости доступа только к публичным API.
- Class.getDeclaredMethods - возвращает массив всех методов, объявленных в классе. Полезно для перебора и фильтрации.
- Class.getDeclaredConstructor - аналогичный способ получения конструкторов.
- MethodHandles.Lookup и MethodHandle - современная альтернатива для более быстрого вызова и работы с лукапами, особенно внутри модульной системы.
Выбор зависит от требований: если нужен доступ к приватным методам, то getDeclaredMethod удобен; для публичных и унаследованных методов предпочтительнее getMethod; для высокопроизводительных вызовов или доступа к приватным методам в условиях модулей - MethodHandles с приватным Lookup.
Аналоги в других языках
Краткое сравнение с отражением в популярных языках и примеры.
- PHP:
ReflectionClass::getMethod(string $name). ВозвращаетReflectionMethod. Пример:class A { private function p() { return 'x'; } } $ref = new ReflectionClass('A'); $m = $ref->getMethod('p'); $m->setAccessible(true); echo $m->invoke(new A());x
- JavaScript: динамический доступ к свойствам объекта. Аналога отражения на уровне класса нет, но доступ выполняется по имени:
obj[methodName].call(obj, ...). Пример:const obj = { hello() { return 'hi' } }; console.log(obj['hello']());hi
- Python:
getattr(obj, 'name')или модульinspect. Пример:class A: def foo(self): return 'ok' print(getattr(A(), 'foo')())ok
- C#:
Type.GetMethodиBindingFlagsдля приватных методов. Пример:class A { private string P() => "x"; } var m = typeof(A).GetMethod("P", BindingFlags.NonPublic | BindingFlags.Instance); Console.WriteLine(m.Invoke(new A(), null));x
- Go: пакет
reflect, методValue.MethodByNameвозвращает нулевое значение, если нет. Пример:type S struct{} func (S) Hello() { fmt.Println("h") } var v = reflect.ValueOf(S{}) v.MethodByName("Hello").Call(nil)h
- Kotlin: использует Java рефлексию или kotlin.reflect.KClass для более декларативного API. Пример с Java-рефлексией идентичен приведенным выше.
- Lua: функции обычно хранятся в таблицах; доступ по имени осуществляется как к полю таблицы.
- SQL: отражение методов не применимо; язык не предоставляет такого механизма.
Отличия от Java: во многих языках доступ к приватному API требует специальных флагов или недоступен вовсе; Java предоставляет подробный механизм через Method и возможность принудительного снятия ограничений, но модульная система добавила ограничения на доступ.
Типичные ошибки и их проявления
Частые проблемы при работе с getDeclaredMethod и их проявления в виде исключений.
- NoSuchMethodException - возникает при несовпадении имени или типов параметров.
class A { public void f(int x) {} } A.class.getDeclaredMethod("f"); // сигнатура не совпадаетjava.lang.NoSuchMethodException: A.f()
- NullPointerException - возможна при передаче
nullв качестве имени метода или при неправильном использовании аргументов (зависит от версии JVM). - SecurityException - при наличии SecurityManager, запрещающем рефлексию.
- IllegalAccessException при вызове через
Method.invoke- если метод недоступен и не был открыт черезsetAccessible(true)или модульная система блокирует доступ.Method m = A.class.getDeclaredMethod("priv"); // без setAccessible(true) m.invoke(a);java.lang.IllegalAccessException: class ... cannot access a member of class A with modifiers "private"
- InvocationTargetException - обертка для исключения, брошенного самим вызываемым методом. Полезно распаковывать через
getCause(). - InaccessibleObjectException - в JVM с модульной системой при попытке снять ограничения через
setAccessible(true)или выполнить вызов на закрытом элементе может появиться это исключение.Method m = Hidden.class.getDeclaredMethod("x"); m.setAccessible(true); m.invoke(...);java.lang.reflect.InaccessibleObjectException: Unable to make ... accessible: module not open to reflection
Изменения и поведение в новых версиях Java
Важные изменения, повлиявшие на работу с рефлексией в последних релизах:
- Введение модульной системы (Java 9) добавило ограничения на доступ к приватным классам и членам из других модулей. Прямой вызов
setAccessible(true)может приводить кInaccessibleObjectException, если модуль не открыт для рефлексии. - Появление API
MethodHandlesиMethodHandleкак производительного и безопасного аналога традиционной рефлексии для динамического вызова и манипуляции вызовами. - Поведение методов и исключений в целом стабильно; сигнатура
getDeclaredMethodне менялась, но окружение безопасности и модульность стали основными факторами, влияющими на успешность доступа.
Расширенные и нетипичные сценарии применения
Несколько продвинутых примеров с пояснениями.
1) Использование getDeclaredMethod с преобразованием параметров примитивных типов и распаковкой результата
class M {
private static double mul(double a, double b) { return a * b; }
}
Method mm = M.class.getDeclaredMethod("mul", double.class, double.class);
mm.setAccessible(true);
Object r = mm.invoke(null, 2.5, 4.0); // static - первый аргумент null
System.out.println(r);
10.0
Пояснение: для статических методов первый аргумент у invoke равен null. Для примитивов выполняется автоупаковка/распаковка.
2) Получение MethodHandle из Method для повышения производительности
class S { private String secret() { return "s"; } }
Method m = S.class.getDeclaredMethod("secret");
m.setAccessible(true);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle mh = lookup.unreflect(m); // преобразование
System.out.println((String) mh.invokeExact(new S()));
s
Пояснение: преобразование через unreflect дает MethodHandle, который при частых вызовах может работать быстрее, чем Method.invoke.
3) Доступ к приватному методу из другого модуля с использованием приватного Lookup (Java 9+)
// требуется, чтобы модуль с цельным классом открывал пакет
Class<?> target = Secret.class;
Method m = target.getDeclaredMethod("priv");
// если setAccessible запрещен, применяется privateLookupIn
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(target, MethodHandles.lookup());
MethodHandle mh = lookup.unreflect(m);
Object out = mh.invoke(newInstanceOfSecret);
System.out.println(out);
... (результат работы метода priv)
Пояснение: privateLookupIn позволяет получить доступ в рамках модульной системы при наличии соответствующих прав или открытий модулей.
4) Поиск перегруженных методов по точной сигнатуре
class O {
public void p(int a) {}
public void p(String s) {}
}
// для выбора нужной перегрузки
Method m1 = O.class.getDeclaredMethod("p", int.class);
Method m2 = O.class.getDeclaredMethod("p", String.class);
System.out.println(m1.getName() + " -> " + Arrays.toString(m1.getParameterTypes()));
System.out.println(m2.getName() + " -> " + Arrays.toString(m2.getParameterTypes()));
p -> [int] p -> [class java.lang.String]
Пояснение: выбор перегрузки осуществляется по набору типов параметров, поэтому важно точно указывать примитивные классы (например, int.class) и массивные типы для varargs.
5) Обработка исключений, брошенных вызываемым методом
class Ex { public void explode() { throw new RuntimeException("boom"); } }
Method m = Ex.class.getDeclaredMethod("explode");
try {
m.invoke(new Ex());
} catch (InvocationTargetException e) {
System.out.println(e.getCause().getMessage());
}
boom
Пояснение: исключение, брошенное внутри вызываемого метода, приходит в виде причины InvocationTargetException и требует распаковки через getCause().
джава Class.getDeclaredMethod function comments
- джава Class.getDeclaredMethod - аргументы и возвращаемое значение
- Функция java Class.getDeclaredMethod - описание
- Class.getDeclaredMethod - примеры
- Class.getDeclaredMethod - похожие методы на java
- Class.getDeclaredMethod на javascript, c#, python, php
- Class.getDeclaredMethod изменения java
- Примеры Class.getDeclaredMethod на джава