Spec-Zone.ru › OpenJDK 8

Класс MethodHandles

  • java.lang.Object
    • java.lang.invoke.MethodHandles

public class MethodHandles
extends Object

Этот класс состоит исключительно из статических методов, которые работают с обработчиками методов или возвращают их. Они делятся на несколько категорий:

  • Методы поиска, которые помогают создать обработчики методов и полей.
  • Комбинирующие методы, которые объединяют или преобразуют существующие обработчики методов в новые.
  • Другие методы-фабрики для создания обработчиков методов, которые эмулируют другие общие операции JVM или схемы управления потоком.

С момента:
1.7

Вложенные классы

Модификатор и тип Класс и описание
static class  MethodHandles.Lookup

Объект поиска — это фабрика для создания обработчиков методов, когда для создания требуется проверка доступа.

Методы

Модификатор и тип Метод и описание
static MethodHandle arrayElementGetter(Class<?> arrayClass)

Создает обработчик метода для чтения элементов массива.

static MethodHandle arrayElementSetter(Class<?> arrayClass)

Создает обработчик метода для записи элементов массива.

static MethodHandle catchException(MethodHandle target, Class<? extends Throwable> exType, MethodHandle handler)

Создает обработчик метода, который адаптирует целевой обработчик метода, выполняя его внутри обработчика исключений.

static MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter)

Адаптирует целевой обработчик метода, предварительно обрабатывая подпоследовательность его аргументов с помощью фильтра (другой обработчик метода).

static MethodHandle constant(Class<?> type, Object value)

Создает обработчик метода требуемого типа возврата, который каждый раз при вызове возвращает заданное константное значение.

static MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes)

Создаёт обработчик метода, который отбросит некоторые фиктивные аргументы перед вызовом другого указанного целевого обработчика метода.

static MethodHandle dropArguments(MethodHandle target, int pos, List<Class<?>> valueTypes)

Создаёт обработчик метода, который отбросит некоторые фиктивные аргументы перед вызовом другого указанного целевого обработчика метода.

static MethodHandle exactInvoker(MethodType type)

Создает специальный обработчик вызова метода, который может использоваться для вызова любого обработчика метода заданного типа, как если бы он был вызван с помощью invokeExact.

static MethodHandle explicitCastArguments(MethodHandle target, MethodType newType)

Создает обработчик метода, который адаптирует тип данного обработчика метода к новому типу путём парной конвертации аргументов и типов возвращаемых значений.

static MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters)

Адаптирует целевой обработчик метода, предварительно обрабатывая один или несколько его аргументов с помощью собственной функции фильтра для каждого, и затем вызывает целевой обработчик с каждым предварительно обработанным аргументом, заменённым результатом его соответствующей функции фильтра.

static MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter)

Адаптирует целевой обработчик метода, пост-обрабатывая возвращаемое значение (если таковое имеется) с помощью фильтра (другой обработчик метода).

static MethodHandle foldArguments(MethodHandle target, MethodHandle combiner)

Адаптирует целевой обработчик метода, предварительно обработав некоторые из его аргументов, и затем вызывает целевой обработчик с результатом предварительной обработки, вставленным в исходную последовательность аргументов.

static MethodHandle guardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback)

Создаёт обработчик метода, который адаптирует целевой обработчик метода, защищая его с помощью проверки, обработчика метода с булевым значением.

static MethodHandle identity(Class<?> type)

Создаёт обработчик метода, который возвращает свой единственный аргумент при вызове.

static MethodHandle insertArguments(MethodHandle target, int pos, Object... values)

Предоставляет целевому обработчику метода один или несколько связанных аргументов заранее перед вызовом обработчика метода.

static MethodHandle invoker(MethodType type)

Создаёт специальный обработчик вызова метода, который может использоваться для вызова любого совместимого с данным типом обработчика метода, как если бы он был вызван с помощью invoke.

static MethodHandles.Lookup lookup()

Возвращает lookup object с полными возможностями для эмуляции всех поддерживаемых поведенческих особенностей байткода вызывающего метода.

static MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder)

Создаёт обработчик метода, который адаптирует последовательность вызова данного обработчика метода к новому типу путём переупорядочивания аргументов.

static MethodHandles.Lookup publicLookup()

Возвращает lookup object, который доверен минимально.

static <T extends Member>
T
reflectAs(Class<T> expected, MethodHandle target)

Выполняет неконтролируемое "раскрытие" прямого обработчика метода.

static MethodHandle spreadInvoker(MethodType type, int leadingArgCount)

Создаёт обработчик метода, который вызовет любой обработчик метода указанного type, с заданным количеством конечных аргументов, заменённых одним конечным Object[] массивом.

static MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType)

Создаёт обработчик метода, который будет выбрасывать исключения указанного exType.

Методы, унаследованные от класса java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Методы

lookup

public static MethodHandles.Lookup lookup()

Возвращает lookup object с полными возможностями для эмуляции всех поддерживаемых поведенческих характеристик байткода вызывающего объекта. Эти возможности включают доступ к закрытым членам вызывающего объекта. Методы-фабрики объекта lookup могут создавать прямые обработчики методов для любого члена, к которому вызывающий объект имеет доступ через байткод, включая защищенные и закрытые поля и методы. Этот объект lookup является возможностью, которую можно делегировать доверенным агентам. Не храните его в местах, к которым может получить доступ недоверенный код.

Этот метод чувствителен к вызывающему объекту, что означает, что он может возвращать разные значения для разных вызывающих объектов.

Для любого данного класса вызывающего объекта C, объект lookup, возвращённый этим вызовом, обладает эквивалентными возможностями любому объекту lookup, предоставленному JVM методу инициализации инструкции invokedynamic, выполняющейся в том же классе вызывающего объекта C.

Возвращает:
объект lookup для вызывающего объекта этого метода с доступом к закрытым членам

publicLookup

public static MethodHandles.Lookup publicLookup()

Возвращает lookup object, который минимально надёжен. Он может использоваться только для создания обработчиков методов для публично доступных полей и методов.

По умолчанию, класс lookup этого объекта lookup будет Object.

Обсуждение: Класс lookup может быть изменён на любой другой класс C с помощью выражения вида publicLookup().in(C.class). Поскольку все классы имеют равный доступ к общедоступным именам, такое изменение не предоставит новых прав доступа. Объект public lookup всегда подлежит проверкам менеджера безопасности. Также он не может получить доступ к методам, чувствительным к вызывающему объекту.

Возвращает:
объект lookup, который минимально надёжен

reflectAs

public static <T extends Member> T reflectAs(Class<T> expected,
                                             MethodHandle target)

Выполняет неконтролируемое "раскрытие" прямого обработчика метода. Результат аналогичен тому, как если бы пользователь получил объект lookup с достаточными возможностями для раскрытия целевого обработчика метода, вызвав Lookup.revealDirect на целевом обработчике для получения его символической ссылки, а затем MethodHandleInfo.reflectAs для разрешения символической ссылки на член.

Если менеджер безопасности существует, вызывается его метод checkPermission с разрешением ReflectPermission("suppressAccessChecks").

Параметры типа:
T - желаемый тип результата, либо Member, либо подтип
Параметры:
target - прямой обработчик метода, который требуется раскрыть до символических ссылок
expected - объект класса, представляющий желаемый тип результата T
Возвращает:
ссылку на объект метода, конструктора или поля
Исключения:
SecurityException - если у вызывающего объекта недостаточно привилегий для вызова setAccessible
NullPointerException - если любой из аргументов имеет значение null
IllegalArgumentException - если целевой объект не является прямым обработчиком метода
ClassCastException - если член не является ожидаемого типа
С:
1.8

arrayElementGetter

public static MethodHandle arrayElementGetter(Class<?> arrayClass)
                                       throws IllegalArgumentException

Создаёт обработчик метода, предоставляющий доступ для чтения к элементам массива. Тип обработчика метода будет иметь тип возвращаемого значения, соответствующий типу элемента массива. Его первый аргумент будет типом массива, а второй — int.

Параметры:
arrayClass - тип массива
Возвращает:
обработчик метода, который может загружать значения из заданного типа массива
Исключения:
NullPointerException - если аргумент имеет значение null
IllegalArgumentException - если arrayClass не является типом массива

arrayElementSetter

public static MethodHandle arrayElementSetter(Class<?> arrayClass)
                                       throws IllegalArgumentException

Создаёт обработчик метода, предоставляющий доступ для записи к элементам массива. Тип обработчика метода будет иметь тип возврата void. Его последний аргумент будет типом элемента массива. Первый и второй аргументы будут типом массива и целым числом.

Параметры:
arrayClass - класс массива
Возвращает:
обработчик метода, который может сохранять значения в массив данного типа
Исключения:
NullPointerException - если аргумент имеет значение null
IllegalArgumentException - если arrayClass не является типом массива

spreadInvoker

public static MethodHandle spreadInvoker(MethodType type,
                                         int leadingArgCount)

Создаёт обработчик метода, который будет вызывать любой обработчик метода данного type, с заданным числом хвостовых аргументов, заменённых на один хвостовой Object[] массив. Результирующий вызывающий объект будет обработчиком метода со следующими аргументами:

  • единственный MethodHandle целевой объект
  • ноль или более начальных значений (подсчитывается leadingArgCount)
  • Object[] массив содержащий хвостовые аргументы

Вызывающий объект вызовет свой целевой объект, как вызов invoke со указанными type. То есть, если целевой объект точно соответствует заданному type, он будет вести себя, как invokeExact; в противном случае он будет вести себя так, как если бы asType использовался для преобразования целевого объекта к требуемому type.

Тип возвращаемого вызывающего объекта не будет заданным type, а скорее будет содержать все параметры, кроме первого leadingArgCount заменённые одним массивом типа Object[], который будет последним параметром.

Перед вызовом целевого объекта вызывающий объект будет распределить конечный массив, применить необходимые преобразования ссылок и разворачивать примитивные аргументы. Если при вызове вызывающего объекта, аргумент массива не содержит правильного количества элементов, вызывающий объект будет выбрасывать IllegalArgumentException вместо вызова целевого объекта.

Этот метод эквивалентен следующему коду (хотя он может быть более эффективным):

MethodHandle invoker = MethodHandles.invoker(type);
int spreadArgCount = type.parameterCount() - leadingArgCount;
invoker = invoker.asSpreader(Object[].class, spreadArgCount);
return invoker;
Этот метод не генерирует исключений отражения или безопасности.
Параметры:
type - желаемый тип целевого объекта
leadingArgCount - количество фиксированных аргументов, которые будут переданы целевому объекту без изменений
Возвращает:
обработчик метода, подходящий для вызова любого обработчика метода заданного типа
Исключения:
NullPointerException - если type имеет значение null
IllegalArgumentException - если leadingArgCount не находится в диапазоне от 0 до type.parameterCount() включительно, или если тип результирующего обработчика метода будет иметь слишком много параметров

exactInvoker

public static MethodHandle exactInvoker(MethodType type)

Создаёт специальный обработчик вызова метода, который может использоваться для вызова любого обработчика метода заданного типа, как если бы он был вызван с помощью invokeExact. Результирующий вызывающий объект будет иметь тип, точно равный желаемому типу, за исключением того, что он будет принимать дополнительный ведущий аргумент типа MethodHandle.

Этот метод эквивалентен следующему коду (хотя он может быть более эффективным): publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)

Обсуждение: Обработчики вызова методов могут быть полезны при работе с переменными обработчиками методов неизвестных типов. Например, для эмуляции вызова invokeExact к переменной обработчику метода M, извлеките его тип T, найдите обработчик вызова метода X для T, и вызовите обработчик вызова метода, как X.invoke(T, A...). (Не будет работать вызов X.invokeExact, так как тип T неизвестен.) Если требуются распространение, сбор или другие преобразования аргументов, они могут быть применены один раз к вызывающему объекту X и повторно использованы для многих значений обработчика метода M, если они совместимы с типом X.

(Примечание: обработчик вызова метода недоступен через API ядра Reflection. Попытка вызвать java.lang.reflect.Method.invoke на объявленном invokeExact или invoke методе вызовет UnsupportedOperationException.)

Этот метод не генерирует исключений отражения или безопасности.

Параметры:
type - желаемый тип целевого объекта
Возвращает:
обработчик метода, подходящий для вызова любого обработчика метода заданного типа
Исключения:
IllegalArgumentException - если тип результирующего обработчика метода будет иметь слишком много параметров

invoker

public static MethodHandle invoker(MethodType type)

Создаёт специальную обработчик вызова метода, который может использоваться для вызова любого обработчика метода, совместимого с заданным типом, как если бы посредством invoke. Полученный обработчик вызова будет иметь тип, точно равный желаемому типу, за исключением того, что он будет принимать дополнительный ведущий аргумент типа MethodHandle.

Перед вызовом целевого метода, если целевой метод отличается от ожидаемого типа, обработчик вызова применит необходимые преобразования типов ссылок и преобразования в/из примитивные типы, или расширит примитивные значения, как если бы посредством asType. Аналогично, возвращаемое значение будет преобразовано по мере необходимости. Если целевой метод является методом с переменным числом аргументов, необходимое преобразование арности будет выполнено, снова как если бы посредством asType.

Этот метод эквивалентен следующему коду (хотя может быть более эффективным): publicLookup().findVirtual(MethodHandle.class, "invoke", type)

Обсуждение: Общие типы методов — это типы, которые упоминают только Object аргументы и возвращаемые значения. Обработчик вызова для такого типа способен вызывать любой обработчик метода с такой же арностью, как и общий тип.

(Примечание: метод обработчика вызова недоступен через API ядра рефлексии. Попытка вызвать java.lang.reflect.Method.invoke на объявленном invokeExact или invoke методе вызовет UnsupportedOperationException.)

Этот метод не вызывает рефлексивных или защитных исключений.

Параметры:
type - желаемый тип целевого метода
Возвращает:
обработчик метода, подходящий для вызова любого обработчика метода, преобразуемого в заданный тип
Исключения:
IllegalArgumentException - если тип результирующего обработчика метода будет иметь слишком много параметров

explicitCastArguments

public static MethodHandle explicitCastArguments(MethodHandle target,
                                                 MethodType newType)

Создаёт обработчик метода, который адаптирует тип данного обработчика метода к новому типу путём попарного преобразования типов аргументов и возвращаемого значения. Исходный тип и новый тип должны иметь одинаковое количество аргументов. Результирующий обработчик метода гарантированно сообщит тип, равный желаемому новому типу.

Если исходный тип и новый тип равны, возвращает target.

Разрешены те же преобразования, что и для MethodHandle.asType, и некоторые дополнительные преобразования также применяются, если эти преобразования не удаются. Для типов T0, T1, одно из следующих преобразований применяется, если возможно, до или вместо любых преобразований, выполняемых asType:

  • Если T0 и T1 — ссылки, а T1 — тип интерфейса, то значение типа T0 передаётся как T1 без преобразования типа. (Это обработка интерфейсов следует использованию верификатора байт-кода.)
  • Если T0 — boolean, а T1 — другой примитивный тип, boolean преобразуется в значение типа byte, 1 для true, 0 для false. (Эта обработка соответствует использованию верификатора байт-кода.)
  • Если T1 — boolean, а T0 — другой примитивный тип, T0 преобразуется в byte через преобразование Java (JLS 5.5), и проверяется младший бит результата, как если бы посредством (x & 1) != 0.
  • Если T0 и T1 — примитивные типы, отличные от boolean, то применяется преобразование Java (JLS 5.5). (В частности, T0 преобразуется в T1 путём расширения и/или сужения.)
  • Если T0 — ссылка, а T1 — примитивный тип, то в процессе выполнения происходит преобразование из ссылки в примитивный тип, возможно, за которым следует преобразование Java (JLS 5.5) примитивного значения, возможно, за которым следует преобразование из byte в boolean путём проверки младшего бита.
  • Если T0 — ссылка, а T1 — примитивный тип, и если ссылка имеет значение null в процессе выполнения, вводится нулевое значение.
Параметры:
target - обработчик метода, который будет вызван после повторного ввода аргументов
newType - ожидаемый тип нового обработчика метода
Возвращает:
обработчик метода, который делегирует целевому методу после выполнения необходимых преобразований аргументов и обеспечивает необходимые преобразования возвращаемого значения
Исключения:
NullPointerException - если любой из аргументов равен null
WrongMethodTypeException - если преобразование невозможно
См. также:
MethodHandle.asType(java.lang.invoke.MethodType)

permuteArguments

public static MethodHandle permuteArguments(MethodHandle target,
                                            MethodType newType,
                                            int... reorder)

Создаёт обработчик метода, который адаптирует последовательность вызова данного обработчика метода к новому типу, переупорядочив аргументы. Результирующий обработчик метода гарантированно сообщит тип, равный желаемому новому типу.

Переданный массив управляет переупорядочиванием. Обозначим количество входных параметров как newType.parameterCount(), и количество выходных параметров как target.type().parameterCount(). Тогда длина массива переупорядочивания должна быть #O, а каждый элемент должен быть неотрицательным числом, меньшим #I. Для каждого N меньше #O, N-й выходной аргумент будет взят из I-го входного аргумента, где I равно reorder[N].

Преобразования аргументов или возвращаемых значений не применяются. Тип каждого входного аргумента, как определяется newType, должен быть идентичен типу соответствующего выходного параметра или параметров в целевом обработчике метода. Тип возвращаемого значения newType должен быть идентичен типу возвращаемого значения исходного целевого метода.

Массив переупорядочивания не обязательно должен указывать фактическое переупорядочение. Входной аргумент будет дублирован, если его индекс появляется более одного раза в массиве, и входной аргумент будет пропущен, если его индекс не появляется в массиве. Как и в случае с dropArguments, входные аргументы, не упомянутые в массиве переупорядочивания, могут иметь любой тип, как определено только newType.

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodType intfn1 = methodType(int.class, int.class);
MethodType intfn2 = methodType(int.class, int.class, int.class);
MethodHandle sub = ... (int x, int y) -> (x-y) ...;
assert(sub.type().equals(intfn2));
MethodHandle sub1 = permuteArguments(sub, intfn2, 0, 1);
MethodHandle rsub = permuteArguments(sub, intfn2, 1, 0);
assert((int)rsub.invokeExact(1, 100) == 99);
MethodHandle add = ... (int x, int y) -> (x+y) ...;
assert(add.type().equals(intfn2));
MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
assert(twice.type().equals(intfn1));
assert((int)twice.invokeExact(21) == 42);
Параметры:
target - обработчик метода, который будет вызван после переупорядочивания аргументов
newType - ожидаемый тип нового обработчика метода
reorder - массив индексов, контролирующий переупорядочение
Возвращает:
обработчик метода, который делегирует целевому методу после удаления неиспользуемых аргументов и перемещения и/или дублирования других аргументов
Исключения:
NullPointerException - если любой из аргументов равен null
IllegalArgumentException - если длина массива индексов не равна арности целевого метода, или если какой-либо элемент массива индексов не является допустимым индексом для параметра newType, или если два соответствующих типа параметров в target.type() и newType не идентичны

constant

public static MethodHandle constant(Class<?> type,
                                    Object value)

Создаёт обработчик метода запрошенного типа, который возвращает заданное константное значение каждый раз при вызове.

Перед возвратом обработчика метода переданное значение преобразуется в запрашиваемый тип. Если запрошенный тип примитивный, то предпринимаются попытки расширения примитивных типов, в противном случае — попытки преобразования ссылок.

Возвращаемый обработчик метода эквивалентен identity(type).bindTo(value).

Параметры:
type - тип возвращаемого значения желаемого обработчика метода
value - значение, которое должно возвращаться
Возвращает:
обработчик метода заданного типа возвращаемого значения и без аргументов, который всегда возвращает данное значение
Исключения:
NullPointerException - если аргумент type равен null
ClassCastException - если значение не может быть преобразовано в требуемый тип возвращаемого значения
IllegalArgumentException - если заданный тип void.class

identity

public static MethodHandle identity(Class<?> type)

Создаёт обработчик метода, который возвращает свой единственный аргумент при вызове.

Параметры:
type - тип единственного параметра и возвращаемого значения желаемого обработчика метода
Возвращает:
унарный обработчик метода, который принимает и возвращает заданный тип
Исключения:
NullPointerException - если аргумент равен null
IllegalArgumentException - если заданный тип void.class

insertArguments

public static MethodHandle insertArguments(MethodHandle target,
                                           int pos,
                                           Object... values)

Обеспечивает целевой обработчик метода одним или несколькими связанными аргументами заранее перед вызовом обработчика метода. Формальные параметры целевого метода, соответствующие связанным аргументам, называются связанными параметрами. Возвращает новый обработчик метода, который сохраняет связанные аргументы. При вызове он получает аргументы для любых несвязанных параметров, связывает сохранённые аргументы с соответствующими параметрами и вызывает исходный целевой метод.

Тип нового обработчика метода будет исключать типы связанных параметров из исходного типа целевого метода, так как новый обработчик метода больше не будет требовать этих аргументов от своих вызывающих сторон.

Каждое переданное значение аргумента должно соответствовать типу соответствующего связанного параметра. Если тип связанного параметра — примитивный, значение аргумента должно быть обёрткой, и будет распаковано для получения примитивного значения.

Аргумент pos выбирает, какие параметры будут связаны. Он может принимать значения от нуля до N-L (включительно), где N — арность целевого обработчика метода, а L — длина массива значений.

Параметры:
target - обработчик метода, который будет вызван после вставки аргумента
pos - место вставки аргумента (ноль для первого)
values - последовательность аргументов для вставки
Возвращает:
обработчик метода, который вставляет дополнительный аргумент перед вызовом исходного обработчика метода
Исключения:
NullPointerException - если целевой метод или массив values равен null
См. также:
MethodHandle.bindTo(java.lang.Object)

dropArguments

public static MethodHandle dropArguments(MethodHandle target,
                                         int pos,
                                         List<Class<?>> valueTypes)

Создаёт обработчик метода, который будет отбрасывать некоторые фиктивные аргументы перед вызовом другого указанного обработчика метода target. Тип нового обработчика метода будет таким же, как тип целевого, за исключением того, что он также будет включать типы фиктивных аргументов в определённой позиции.

Аргумент pos может принимать значения от нуля до N, где N — арность целевого метода. Если pos равно нулю, фиктивные аргументы будут предшествовать реальным аргументам целевого метода; если pos равно N, они будут следовать за ними.

Пример:

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
assertEquals(bigType, d0.type());
assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));

Этот метод также эквивалентен следующему коду:

dropArguments (target, pos, valueTypes.toArray(new Class[0]))
Параметры:
target - обработчик метода для вызова после отбрасывания аргументов
valueTypes - тип(ы) аргумента(ов) для отбрасывания
pos - позиция первого аргумента для отбрасывания (ноль для самого левого)
Возвращает:
обработчик метода, который отбрасывает аргументы заданных типов перед вызовом исходного обработчика метода
Исключение:
NullPointerException - если целевой обработчик равен null, или если массив valueTypes или любой из его элементов равен null
IllegalArgumentException - если любой элемент массива valueTypes равен void.class, или если pos отрицательно или больше арности целевого метода, или если у нового обработчика метода слишком много параметров

dropArguments

public static MethodHandle dropArguments(MethodHandle target,
                                         int pos,
                                         Class<?>... valueTypes)

Создаёт обработчик метода, который будет отбрасывать некоторые фиктивные аргументы перед вызовом другого указанного обработчика метода target. Тип нового обработчика метода будет таким же, как тип целевого, за исключением того, что он также будет включать типы фиктивных аргументов в определённой позиции.

Аргумент pos может принимать значения от нуля до N, где N — арность целевого метода. Если pos равно нулю, фиктивные аргументы будут предшествовать реальным аргументам целевого метода; если pos равно N, они будут следовать за ними.

Пример:

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
MethodHandle d0 = dropArguments(cat, 0, String.class);
assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
MethodHandle d1 = dropArguments(cat, 1, String.class);
assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
MethodHandle d2 = dropArguments(cat, 2, String.class);
assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));

Этот метод также эквивалентен следующему коду:

dropArguments (target, pos, Arrays.asList(valueTypes))
Параметры:
target - обработчик метода для вызова после отбрасывания аргументов
valueTypes - тип(ы) аргумента(ов) для отбрасывания
pos - позиция первого аргумента для отбрасывания (ноль для самого левого)
Возвращает:
обработчик метода, который отбрасывает аргументы заданных типов перед вызовом исходного обработчика метода
Исключение:
NullPointerException - если целевой обработчик равен null, или если массив valueTypes или любой из его элементов равен null
IllegalArgumentException - если любой элемент массива valueTypes равен void.class, или если pos отрицательно или больше арности целевого метода, или если у нового обработчика метода слишком много параметров

filterArguments

public static MethodHandle filterArguments(MethodHandle target,
                                           int pos,
                                           MethodHandle... filters)

Адаптирует целевой обработчик метода, предварительно обрабатывая один или несколько его аргументов с помощью каждой своей унарной функции фильтра, а затем вызывая целевой обработчик метода с каждым предварительно обработанным аргументом, заменённым результатом соответствующей функции фильтра.

Предварительная обработка выполняется одним или несколькими обработчиками метода, указанными в элементах массива filters. Первый элемент массива фильтров соответствует аргументу pos целевого метода, и так далее последовательно.

Нулевые аргументы в массиве обрабатываются как тождественные функции, и соответствующие аргументы остаются неизменными. (Если в массиве нет ненулевых элементов, возвращается исходный целевой обработчик.) Каждый фильтр применяется к соответствующему аргументу адаптера.

Если фильтр F применяется к аргументу N целевого метода, то F должен быть обработчиком метода, который принимает ровно один аргумент. Тип единственного аргумента F заменяет соответствующий тип аргумента целевого метода в результирующем адаптированном обработчике метода. Тип возвращаемого значения F должен быть идентичен соответствующему типу параметра целевого метода.

Ошибка, если элементы filters (нулевые или не нулевые) не соответствуют позициям аргументов в целевом методе.

Пример:

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
MethodHandle upcase = lookup().findVirtual(String.class,
  "toUpperCase", methodType(String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
MethodHandle f0 = filterArguments(cat, 0, upcase);
assertEquals("Xy", (String) f0.invokeExact("x", "y")); // Xy
MethodHandle f1 = filterArguments(cat, 1, upcase);
assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY
MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY

Вот псевдокод для результирующего адаптера:

V target(P... p, A[i]... a[i], B... b);
A[i] filter[i](V[i]);
T adapter(P... p, V[i]... v[i], B... b) {
  return target(p..., f[i](v[i])..., b...);
}
Параметры:
target - обработчик метода для вызова после фильтрации аргументов
pos - позиция первого аргумента для фильтрации
filters - обработчики методов для вызова вначале на отфильтрованных аргументах
Возвращает:
обработчик метода, который включает указанную логику фильтрации аргументов
Исключение:
NullPointerException - если целевой обработчик равен null или если массив filters равен null
IllegalArgumentException - если ненулевой элемент filters не соответствует соответствующему типу аргумента целевого метода, как описано выше, или если pos+filters.length больше target.type().parameterCount(), или если у результирующего обработчика метода слишком много параметров

collectArguments

public static MethodHandle collectArguments(MethodHandle target,
                                            int pos,
                                            MethodHandle filter)

Адаптирует целевой обработчик метода, предварительно обрабатывая подпоследовательность его аргументов фильтром (другим обработчиком метода). Предварительно обработанные аргументы заменяются результатом (если таковой имеется) функции фильтра. Затем целевой обработчик вызывается с изменённым (как правило, укороченным) списком аргументов.

Если фильтр возвращает значение, целевой обработчик должен принять это значение в качестве аргумента на позиции pos, перед и/или после любых аргументов, не переданных фильтру. Если фильтр возвращает void, целевой обработчик должен принять все аргументы, не переданные фильтру. Аргументы не переупорядочиваются, а возвращаемое фильтром значение заменяет (по порядку) всю подпоследовательность аргументов, первоначально переданных адаптеру.

Типы аргументов (если таковые имеются) фильтра заменяют ноль или один тип аргументов целевого метода в позиции pos в результирующем адаптированном обработчике метода. Тип возвращаемого значения фильтра (если таковой имеется) должен быть идентичен типу аргумента целевого метода на позиции pos, и этот аргумент целевого метода обеспечивается возвращаемым значением фильтра.

Во всех случаях pos должно быть больше или равно нулю, а pos должно быть меньше или равно арности целевого метода.

Пример:

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle deepToString = publicLookup()
  .findStatic(Arrays.class, "deepToString", methodType(String.class, Object[].class));

MethodHandle ts1 = deepToString.asCollector(String[].class, 1);
assertEquals("[strange]", (String) ts1.invokeExact("strange"));

MethodHandle ts2 = deepToString.asCollector(String[].class, 2);
assertEquals("[up, down]", (String) ts2.invokeExact("up", "down"));

MethodHandle ts3 = deepToString.asCollector(String[].class, 3);
MethodHandle ts3_ts2 = collectArguments(ts3, 1, ts2);
assertEquals("[top, [up, down], strange]",
             (String) ts3_ts2.invokeExact("top", "up", "down", "strange"));

MethodHandle ts3_ts2_ts1 = collectArguments(ts3_ts2, 3, ts1);
assertEquals("[top, [up, down], [strange]]",
             (String) ts3_ts2_ts1.invokeExact("top", "up", "down", "strange"));

MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3);
assertEquals("[top, [[up, down, strange], charm], bottom]",
             (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));

Вот псевдокод для результирующего адаптера:

T target(A...,V,C...);
V filter(B...);
T adapter(A... a,B... b,C... c) {
  V v = filter(b...);
  return target(a...,v,c...);
}
// and if the filter has no arguments:
T target2(A...,V,C...);
V filter2();
T adapter2(A... a,C... c) {
  V v = filter2();
  return target2(a...,v,c...);
}
// and if the filter has a void return:
T target3(A...,C...);
void filter3(B...);
void adapter3(A... a,B... b,C... c) {
  filter3(b...);
  return target3(a...,c...);
}

Адаптер сбора collectArguments(mh, 0, coll) эквивалентен адаптеру, который сначала «сворачивает» затронутые аргументы, а затем отбрасывает их, в отдельных шагах следующим образом:

mh = MethodHandles.dropArguments(mh, 1, coll.type().parameterList()); //step 2
mh = MethodHandles.foldArguments(mh, coll); //step 1
Если целевой обработчик метода не потребляет аргументы помимо результата (если таковой имеется) фильтра coll, то collectArguments(mh, 0, coll) эквивалентен filterReturnValue(coll, mh). Если обработчик метода фильтра coll потребляет один аргумент и генерирует ненулевое значение результата, то collectArguments(mh, N, coll) эквивалентен filterArguments(mh, N, coll). Другие эквивалентности возможны, но потребуют перестановки аргументов.
Параметры:
target - обработчик метода для вызова после фильтрации подпоследовательности аргументов
pos - позиция первого аргумента адаптера для передачи фильтру и/или аргумента целевого метода, который получает результат фильтра
filter - обработчик метода для вызова на подпоследовательности аргументов
Возвращает:
обработчик метода, который включает указанную логику фильтрации подпоследовательности аргументов
Исключение:
NullPointerException - если любой из аргументов равен null
IllegalArgumentException - если тип возвращаемого значения filter не void и не совпадает с аргументом pos целевого метода, или если pos не находится в диапазоне от 0 до арности целевого метода включительно, или если у результирующего обработчика метода слишком много параметров
См. также:
foldArguments(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle), filterArguments(java.lang.invoke.MethodHandle, int, java.lang.invoke.MethodHandle...), filterReturnValue(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle)

filterReturnValue

public static MethodHandle filterReturnValue(MethodHandle target,
                                             MethodHandle filter)

Адаптирует целевой обработчик метода, пост-обрабатывая его возвращаемое значение (если таковое имеется) фильтром (другим обработчиком метода). Результат фильтра возвращается адаптером.

Если целевой метод возвращает значение, фильтр должен принять это значение в качестве единственного аргумента. Если целевой метод возвращает void, фильтр не должен принимать никаких аргументов.

Тип возвращаемого значения фильтра заменяет тип возвращаемого значения целевого метода в результирующем адаптированном обработчике метода. Тип аргумента фильтра (если таковой имеется) должен быть идентичен типу возвращаемого значения целевого метода.

Пример:

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
MethodHandle length = lookup().findVirtual(String.class,
  "length", methodType(int.class));
System.out.println((String) cat.invokeExact("x", "y")); // xy
MethodHandle f0 = filterReturnValue(cat, length);
System.out.println((int) f0.invokeExact("x", "y")); // 2

Вот псевдокод для результирующего адаптера:

V target(A...);
T filter(V);
T adapter(A... a) {
  V v = target(a...);
  return filter(v);
}
// and if the target has a void return:
void target2(A...);
T filter2();
T adapter2(A... a) {
  target2(a...);
  return filter2();
}
// and if the filter has a void return:
V target3(A...);
void filter3(V);
void adapter3(A... a) {
  V v = target3(a...);
  filter3(v);
}
Параметры:
target - обработчик метода для вызова до фильтрации возвращаемого значения
filter - обработчик метода для вызова над возвращаемым значением
Возвращает:
обработчик метода, который включает указанную логику фильтрации возвращаемого значения
Исключение:
NullPointerException - если любой из аргументов равен null
IllegalArgumentException - если список аргументов filter не соответствует типу возвращаемого значения целевого метода, как описано выше

foldArguments

public static MethodHandle foldArguments(MethodHandle target,
                                         MethodHandle combiner)

Адаптирует целевой обработчик метода, предварительно обработав некоторые его аргументы, а затем вызвав целевой обработчик с результатом предварительной обработки, вставленным в исходную последовательность аргументов.

Предварительная обработка выполняется с помощью combiner, второго обработчика метода. Из аргументов, переданных адаптеру, первые N аргументов копируются в комбинирующий обработчик, который затем вызывается. (Здесь N определяется как количество параметров комбинирующего обработчика.) После этого управление передаётся целевому обработчику, при этом любой результат от комбинирующего обработчика вставляется перед исходными N входными аргументами.

Если комбинирующий обработчик возвращает значение, тип первого параметра целевого обработчика должен быть идентичен типу возвращаемого значения комбинирующего обработчика, а следующие N типы параметров целевого обработчика должны точно соответствовать параметрам комбинирующего обработчика.

Если комбинирующий обработчик возвращает void, результат не будет вставлен, и первые N типы параметров целевого обработчика должны точно соответствовать параметрам комбинирующего обработчика.

Полученный адаптер имеет тот же тип, что и целевой обработчик, за исключением того, что тип первого параметра отбрасывается, если он соответствует результату комбинирующего обработчика.

(Обратите внимание, что dropArguments можно использовать для удаления любых аргументов, которые либо комбинирующий обработчик, либо целевой обработчик не хотят получать. Если некоторые из входных аргументов предназначены только для комбинирующего обработчика, рассмотрите использование asCollector вместо этого, так как эти аргументы не должны быть в стеке при входе в целевой обработчик.)

Пример:

import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle trace = publicLookup().findVirtual(java.io.PrintStream.class,
  "println", methodType(void.class, String.class))
    .bindTo(System.out);
MethodHandle cat = lookup().findVirtual(String.class,
  "concat", methodType(String.class, String.class));
assertEquals("boojum", (String) cat.invokeExact("boo", "jum"));
MethodHandle catTrace = foldArguments(cat, trace);
// also prints "boo":
assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));

Вот псевдокод для полученного адаптера:

// there are N arguments in A...
T target(V, A[N]..., B...);
V combiner(A...);
T adapter(A... a, B... b) {
  V v = combiner(a...);
  return target(v, a..., b...);
}
// and if the combiner has a void return:
T target2(A[N]..., B...);
void combiner2(A...);
T adapter2(A... a, B... b) {
  combiner2(a...);
  return target2(a..., b...);
}
Параметры:
target - обработчик метода, который вызывается после комбинирования аргументов
combiner - обработчик метода, который вызывается первоначально по входным аргументам
Возвращает:
обработчик метода, который включает указанную логику сворачивания аргументов
Исключения:
NullPointerException - если какой-либо аргумент имеет значение null
IllegalArgumentException - если тип возвращаемого значения combiner не void и не совпадает с типом первого аргумента целевого обработчика, или если начальные N типы аргументов целевого обработчика (пропуская один, соответствующий типу возвращаемого значения combiner ) не идентичны типам аргументов combiner

guardWithTest

public static MethodHandle guardWithTest(MethodHandle test,
                                         MethodHandle target,
                                         MethodHandle fallback)

Создаёт обработчик метода, который адаптирует целевой обработчик метода, защищая его с помощью проверки, логического обработчика метода. Если проверка не пройдена, вместо этого вызывается обработчик по умолчанию. Все три обработчика метода должны иметь одинаковые соответствующие типы аргументов и возвращаемого значения, за исключением того, что тип возвращаемого значения проверки должен быть boolean, а проверка может иметь меньше аргументов, чем другие два обработчика методов.

Вот псевдокод для полученного адаптера:

boolean test(A...);
T target(A...,B...);
T fallback(A...,B...);
T adapter(A... a,B... b) {
  if (test(a...))
    return target(a..., b...);
  else
    return fallback(a..., b...);
}
Обратите внимание, что аргументы проверки (a... в псевдокоде) не могут быть изменены в процессе выполнения проверки, и поэтому передаются без изменений от вызывающей стороны к целевому или резервному обработчику соответственно.
Параметры:
test - обработчик метода, используемый для проверки, должен возвращать boolean
target - обработчик метода для вызова, если проверка пройдена
fallback - обработчик метода для вызова, если проверка не пройдена
Возвращает:
обработчик метода, который включает указанную логику if/then/else
Исключения:
NullPointerException - если какой-либо аргумент равен null
IllegalArgumentException - если test не возвращает boolean или если типы всех трёх обработчиков методов не совпадают (с типом возвращаемого значения test изменённым для соответствия типу возвращаемого значения целевого обработчика).

catchException

public static MethodHandle catchException(MethodHandle target,
                                          Class<? extends Throwable> exType,
                                          MethodHandle handler)

Создаёт обработчик метода, который адаптирует целевой обработчик метода, выполняя его внутри обработчика исключений. Если целевой обработчик возвращается нормально, адаптер возвращает это значение. Если возникает исключение, соответствующее указанному типу, вместо этого вызывается обработчик по умолчанию по исключению и исходным аргументам.

Целевой обработчик и обработчик должны иметь одинаковые соответствующие типы аргументов и возвращаемого значения, за исключением того, что обработчик может опустить хвостовые аргументы (аналогично предикату в guardWithTest). Кроме того, обработчик должен иметь дополнительный ведущий параметр типа exType или его супертип.

Вот псевдокод для полученного адаптера:

T target(A..., B...);
T handler(ExType, A...);
T adapter(A... a, B... b) {
  try {
    return target(a..., b...);
  } catch (ExType ex) {
    return handler(ex, a...);
  }
}
Обратите внимание, что сохранённые аргументы (a... в псевдокоде) не могут быть изменены при выполнении целевого обработчика, и поэтому передаются без изменений от вызывающей стороны к обработчику, если обработчик вызывается.

Целевой обработчик и обработчик должны возвращать один и тот же тип, даже если обработчик всегда выбрасывает исключение. (Это может произойти, например, потому что обработчик имитирует finally предложение). Чтобы создать такой обработчик, выбрасывающий исключение, комбинируйте логику создания обработчика с throwException, чтобы создать обработчик метода с правильным типом возвращаемого значения.

Параметры:
target - обработчик метода для вызова
exType - тип исключения, которое будет перехвачено обработчиком
handler - обработчик метода для вызова, если возникает соответствующее исключение
Возвращает:
обработчик метода, который включает указанную логику try/catch
Исключения:
NullPointerException - если какой-либо аргумент равен null
IllegalArgumentException - если handler не принимает данный тип исключения или если типы обработчика метода не совпадают по возвращаемым значениям и соответствующим параметрам

throwException

public static MethodHandle throwException(Class<?> returnType,
                                          Class<? extends Throwable> exType)

Создаёт обработчик метода, который будет выбрасывать исключения указанного exType. Обработчик метода будет принимать один аргумент типа exType и сразу же бросит его как исключение. Тип метода номинально указывает возврат returnType. Тип возвращаемого значения может быть любым удобным: это не имеет значения для поведения обработчика метода, так как он никогда не возвращает значение нормально.

Параметры:
returnType - тип возвращаемого значения желаемого обработчика метода
exType - тип параметра желаемого обработчика метода
Возвращает:
обработчик метода, который может выбрасывать указанные исключения
Исключения:
NullPointerException - если какой-либо аргумент равен null

© 1993, 2020, 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