Spec-Zone.ru › OpenJDK 25

Интерфейс InvocationHandler

Все известные реализующие классы:
CompositeDataInvocationHandler, EventHandler, MBeanServerInvocationHandler, RemoteObjectInvocationHandler
public interface InvocationHandler
InvocationHandler — это интерфейс, реализуемый обработчиком вызовов прокси-экземпляра.

Каждый прокси-экземпляр имеет связанный с ним обработчик вызовов. При вызове метода на прокси-экземпляре вызов метода кодируется и отправляется методу invoke соответствующего обработчика вызовов.

С версии:
1.3
См. также:
  • Proxy

Краткое описание методов

Модификатор и тип Метод Описание
Object invoke(Object proxy, Method method, Object[] args)
Обрабатывает вызов метода на прокси-экземпляре и возвращает результат.
static Object invokeDefault(Object proxy, Method method, Object... args)
Вызывает указанный метод по умолчанию на заданном экземпляре 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, содержащее исключение, выброшенное данным методом.
См. также:
  • 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

Сообщить об ошибке или предложить улучшение
Дополнительную справочную информацию по API и документацию для разработчиков см. в разделе Документация по Java SE, где содержатся более подробные описания для разработчиков, концептуальные обзоры, определения терминов, обходные пути и примеры рабочего кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или ее дочерних компаний в США и других странах.
Авторские права © 1993, 2025, Oracle и/или ее дочерние компании, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API