Spec-Zone.ru › OpenJDK 27

Интерфейс 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 может быть интерфейс прокси, один из его суперинтерфейсов или класс Object
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 не может пройти распаковку (unboxing), если соответствующий тип параметра метода является примитивным типом; либо если после возможной распаковки любой из элементов args не может быть присвоен соответствующему типу параметра метода.
IllegalAccessException — если объявляющий класс указанного метода по умолчанию недоступен вызывающему классу
NullPointerException — если proxy или method равен null
Throwable — любое исключение, выброшенное методом по умолчанию
См. Спецификацию виртуальной машины Java:
5.4.3 Resolution
Начиная с:
16

Сообщить об ошибке или предложить улучшение
Дополнительные справочные материалы по API и документацию для разработчиков см. в документации по Java SE, где содержатся более подробные описания, ориентированные на разработчиков, с концептуальными обзорами, определениями терминов, обходными путями и рабочими примерами кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком компании Oracle и/или её дочерних компаний в США и других странах.
Авторские права © 1993, 2026, 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.

Spec-Zone.ru

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