Интерфейс InvocationHandler
- Все известные реализующие классы:
CompositeDataInvocationHandler, EventHandler, MBeanServerInvocationHandler, RemoteObjectInvocationHandler
public interface InvocationHandler
InvocationHandler — это интерфейс, реализуемый обработчиком вызовов прокси-экземпляра. Каждый прокси-экземпляр имеет связанный с ним обработчик вызовов. При вызове метода на прокси-экземпляре вызов метода кодируется и отправляется методу invoke соответствующего обработчика вызовов.
- С версии:
- 1.3
- См. также:
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
Object |
invoke |
Обрабатывает вызов метода на прокси-экземпляре и возвращает результат. |
static Object |
invokeDefault |
Вызывает указанный метод по умолчанию на заданном экземпляре proxy с заданными параметрами. |
Подробное описание методов
invoke
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- Параметры:
-
proxy— прокси-экземпляр, на котором был вызван метод -
method— экземплярMethod, соответствующий интерфейсному методу, вызванному на прокси-экземпляре. Объявляющим классом объектаMethodбудет интерфейс, в котором был объявлен метод, который может являться суперинтерфейсом интерфейса прокси, через который класс прокси наследует данный метод. -
args— массив объектов, содержащий значения аргументов, переданных при вызове метода на прокси-экземпляре, илиnull, если метод интерфейса не принимает аргументов. Аргументы примитивных типов оборачиваются в экземпляры соответствующего класса-обертки примитивного типа, напримерjava.lang.Integerилиjava.lang.Boolean. - Возвращает:
- значение, возвращаемое из вызова метода на прокси-экземпляре. Если объявленный возвращаемый тип метода интерфейса является примитивным типом, то значение, возвращаемое этим методом, должно быть экземпляром соответствующего класса-обертки примитивного типа; в противном случае оно должно относиться к типу, совместимому по присваиванию с объявленным возвращаемым типом. Если значение, возвращаемое этим методом, равно
null, а возвращаемый тип метода интерфейса является примитивным, то при вызове метода на прокси-экземпляре будет выброшено исключениеNullPointerException. Если значение, возвращаемое этим методом, иным образом несовместимо с объявленным типом возвращаемого значения метода интерфейса, как описано выше, при вызове метода на прокси-экземпляре будет выброшено исключениеClassCastException. - Выбрасывает:
-
Throwable— исключение, выбрасываемое из вызова метода на прокси-экземпляре. Тип исключения должен быть совместим либо с любым из типов исключений, объявленных в предложенииthrowsметода интерфейса, либо с непроверяемыми типами исключенийjava.lang.RuntimeExceptionилиjava.lang.Error. Если данный метод выбрасывает проверяемое исключение, несовместимое ни с одним из типов исключений, объявленных в предложенииthrowsметода интерфейса, то вызов метода на прокси-экземпляре выбросит исключениеUndeclaredThrowableException, содержащее исключение, выброшенное данным методом. - См. также:
invokeDefault
static Object invokeDefault(Object proxy, Method method, Object... args) throws Throwable
proxy с заданными параметрами. Заданный method должен быть методом по умолчанию, объявленным в интерфейсе прокси класса proxy или унаследованным от его суперинтерфейса прямо или косвенно. Вызов этого метода ведет себя так, как если бы инструкция invokespecial выполнялась из класса прокси, обращаясь к методу по умолчанию в интерфейсе прокси. Это эквивалентно вызову: X.super.m(A* a) где X — интерфейс прокси, а вызов X.super::m(A*) разрешается в заданный method.
Примеры: интерфейсы A и B оба объявляют реализацию по умолчанию метода m. Интерфейс C расширяет A и наследует метод по умолчанию m от своего суперинтерфейса A.
Следующий код создает прокси-экземпляр, реализующийinterface A { default T m(A a) { return t1; } } interface B { default T m(A a) { return t2; } } interface C extends A {}
A, и вызывает метод по умолчанию A::m. Если прокси-экземпляр реализует одновременноObject proxy = Proxy.newProxyInstance(loader, new Class<?>[] { A.class }, (o, m, params) -> { if (m.isDefault()) { // if it's a default method, invoke it return InvocationHandler.invokeDefault(o, m, params); } });
A и B, каждый из которых предоставляет реализацию по умолчанию метода m, обработчик вызовов может перенаправить вызов метода к A::m или B::m с помощью метода invokeDefault. Например, следующий код делегирует вызов метода интерфейсу B::m. Если прокси-экземпляр реализуетObject proxy = Proxy.newProxyInstance(loader, new Class<?>[] { A.class, B.class }, (o, m, params) -> { if (m.getName().equals("m")) { // invoke B::m instead of A::m Method bMethod = B.class.getMethod(m.getName(), m.getParameterTypes()); return InvocationHandler.invokeDefault(o, bMethod, params); } });
C, который наследует метод по умолчанию m от своего суперинтерфейса A, то вызов метода интерфейса на "m" отправляется в метод invoke обработчика вызовов с объектом-аргументом Method, представляющим метод по умолчанию A::m. Вызов методаObject proxy = Proxy.newProxyInstance(loader, new Class<?>[] { C.class }, (o, m, params) -> { if (m.isDefault()) { // behaves as if calling C.super.m(params) return InvocationHandler.invokeDefault(o, m, params); } });
"m" на этом proxy будет вести себя так, как если бы вызывался C.super::m, что разрешается в вызов A::m. Добавление метода по умолчанию или изменение метода с абстрактного на метод по умолчанию может привести к возникновению исключения, если существующий код пытается вызвать invokeDefault для вызова метода по умолчанию. Например, если C модифицируется для реализации метода по умолчанию m:
Приведенный выше код, создающий прокси-экземплярinterface C extends A { default T m(A a) { return t3; } }
proxy с модифицированным C, выполнится без исключений и приведет к вызову C::m вместо A::m. Ниже приведен еще один пример, в котором создается прокси-экземпляр C, а обработчик вызовов вызывает метод invokeDefault для вызова A::m:
Приведенный выше код успешно выполняется со старой версиейC c = (C) Proxy.newProxyInstance(loader, new Class<?>[] { C.class }, (o, m, params) -> { if (m.getName().equals("m")) { // IllegalArgumentException thrown as {@code A::m} is not a method // inherited from its proxy interface C Method aMethod = A.class.getMethod(m.getName(), m.getParameterTypes()); return InvocationHandler.invokeDefault(o, aMethod params); } }); c.m(...);
C, и вызывается A::m. При выполнении с новой версией C приведенный выше код завершится с ошибкой IllegalArgumentException, поскольку C переопределяет реализацию того же метода, и A::m недоступен для прокси-экземпляра.- Примечание к API:
- Параметр
proxyимеет типObject, а неProxy, чтобы его можно было легко вызывать напрямую из реализацииInvocationHandler::invokeбез необходимости приведения типов. - Параметры:
-
proxy— экземплярProxy, на котором должен быть вызван метод по умолчанию -
method— экземплярMethod, соответствующий методу по умолчанию, объявленному в интерфейсе прокси класса прокси или унаследованному от его суперинтерфейса прямо или косвенно -
args— параметры, используемые для вызова метода; может бытьnull, если количество формальных параметров, требуемых методом, равно нулю. - Возвращает:
- значение, возвращенное в результате вызова метода
- Выбрасывает:
-
IllegalArgumentException— если любое из следующих условийtrue:-
proxyне является прокси-экземпляром; или - заданный
methodне является методом по умолчанию, объявленным в интерфейсе прокси класса прокси, и не унаследован от какого-либо из его суперинтерфейсов; или - заданный
methodпереопределен прямо или косвенно интерфейсами прокси, и ссылка на именованный метод никогда не разрешается в заданныйmethod; или - длина заданного массива
argsне совпадает с количеством параметров вызываемого метода; или - любой из элементов
argsне проходит операцию распаковки, если соответствующий тип параметра метода является примитивным типом; или если после возможной распаковки какой-либо из элементовargsне может быть присвоен соответствующему типу параметра метода.
-
-
IllegalAccessException— если объявляющий класс указанного метода по умолчанию недоступен вызывающему классу -
NullPointerException— еслиproxyилиmethodравенnull -
Throwable— все, что выбрасывается методом по умолчанию - См. Спецификацию виртуальной машины Java:
- 5.4.3 Resolution
- С версии:
- 16
© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/reflect/InvocationHandler.html