Spec-Zone.ru › OpenJDK 25

Интерфейс ClassFileTransform<C extends ClassFileTransform<C,E,B>, E extends ClassFileElement, B extends ClassFileBuilder<E,B>>

Параметры типа:
C — тип преобразования
E — тип элемента-члена
B — тип построителя
Все известные подинтерфейсы:
ClassTransform, CodeTransform, FieldTransform, MethodTransform
public sealed interface ClassFileTransform<C extends ClassFileTransform<C,E,B>, E extends ClassFileElement, B extends ClassFileBuilder<E,B>> permits ClassTransform, FieldTransform, MethodTransform, CodeTransform
Преобразование CompoundElement путем обработки отдельных элементов-членов и передачи результатов в ClassFileBuilder через ClassFileBuilder.transform(CompoundElement, ClassFileTransform). Подтип ClassFileTransform определяется для каждого подтипа CompoundElement и ClassFileBuilder, как показано в приведенной ниже иерархии запечатанных классов.

Например, это простое преобразование CodeModel, которое перенаправляет все вызовы статических методов класса Foo в класс Bar, сохраняя все остальные элементы:

CodeTransform fooToBar = (b, e) -> {
    if (e instanceof InvokeInstruction i
            && i.owner().name().equalsString("Foo")
            && i.opcode() == Opcode.INVOKESTATIC) {
        // remove the old element i by doing nothing to the builder
        // add a new invokestatic instruction to the builder
        b.invokestatic(CD_Bar, i.name().stringValue(), i.typeSymbol(), i.isInterface());
    } else {
        b.with(e);  // leaves the element in place
    }
};
Обратите внимание: если преобразовывать элемент-член не требуется, его следует передать в builder::with. Если никаких действий не выполняется, этот элемент-член отбрасывается.

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

Пользователи могут определить пользовательскую обработку в начале и конце преобразования, переопределив atStart(B) и atEnd(B). Обработчик начала вызывается до обработки любого элемента-члена, а обработчик конца — после обработки всех элементов-членов. Например, обработчик начала можно использовать для добавления дополнительных элементов кода в начало массива кода, а обработчик конца в сочетании с преобразованием с сохранением состояния — для выполнения действий по очистке, таких как определение того, был ли объединен атрибут или следует ли определить новый атрибут. Каждый подтип ClassFileTransform определяет служебный метод endHandler, возвращающий преобразование, у которого есть только обработчик конца.

Преобразования могут иметь состояния, сохраняющиеся при обработке отдельных элементов-членов. Например, если преобразование добавляет аннотацию, оно может отслеживать, встречался ли ему обновленный RuntimeVisibleAnnotationsAttribute и передавался ли он построителю; если еще нет, в обработчике конца оно может передать новый атрибут, содержащий только добавленную аннотацию. Если такое преобразование предназначено для совместного использования или повторного применения, каждое возвращаемое преобразование должно иметь собственное состояние. Каждый подтип ClassFileTransform определяет служебный метод ofStateful, в котором поставщик создает преобразование в исходном состоянии при каждом повторном использовании преобразования.

Преобразования можно объединять с помощью andThen(C). Если это преобразование объединяется с другим, выходные элементы-члены, полученные ClassFileBuilder, становятся входными элементами для следующего преобразования. Композиция позволяет избежать создания промежуточных структур при выполнении нескольких преобразований. Каждый подтип ClassFileTransform реализует andThen(C); обычно пользователям не следует реализовывать этот метод.

Преобразования, работающие с небольшими структурами, можно перенести на содержащие их структуры, чтобы выборочно применять их ко всем вложенным структурам того же типа. Например, CodeTransform можно перенести с помощью ClassTransform.transformingMethodBodies(Predicate, CodeTransform), чтобы преобразовывать тела методов выбранных методов класса, с которым оно работает. Это позволяет пользователям создавать небольшие преобразования и применять их в более широком масштабе.

Помимо ClassFileBuilder.transform(CompoundElement, ClassFileTransform), существуют и другие методы, принимающие преобразование для удобства, например ClassFile.transformClass(ClassModel, ClassTransform), ClassBuilder.transformField(FieldModel, FieldTransform), ClassBuilder.transformMethod(MethodModel, MethodTransform) или MethodBuilder.transformCode(CodeModel, CodeTransform). Это вспомогательные методы, подходящие для большинства сценариев преобразования.

Граф иерархии запечатанных классов:
Sealed class hierarchy graph for ClassFileTransformSealed class hierarchy graph for ClassFileTransform
Начиная с версии:
24

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

Модификатор и тип Метод Описание
void accept(B builder, E element)
Преобразует элемент, выполняя соответствующие действия с построителем.
C andThen(C next)
Объединяет это преобразование с другим; элементы, переданные построителю этого преобразования, станут входными данными для следующего преобразования.
default void atEnd(B builder)
Выполняет заключительное действие при преобразовании сущности class-файла.
default void atStart(B builder)
Выполняет предварительное действие при преобразовании сущности class-файла.

Подробное описание методов

accept

void accept(B builder, E element)
Преобразует элемент, выполняя соответствующие действия с построителем. Используется при преобразовании сущности class-файла (класса, метода, поля, тела метода). Если преобразование не требуется, элемент можно передать в ClassFileBuilder.with(ClassFileElement). Если элемент нужно отбросить, никаких действий выполнять не требуется.

Этот метод вызывается API файлов классов. Пользователям не следует вызывать этот метод.

Параметры:
builder — построитель для новой сущности
element — элемент

atEnd

default void atEnd(B builder)
Выполняет заключительное действие при преобразовании сущности class-файла. Вызывается после передачи всех элементов класса в accept(ClassFileBuilder, ClassFileElement).

Этот метод вызывается API файлов классов. Пользователям не следует вызывать этот метод.

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

atStart

default void atStart(B builder)
Выполняет предварительное действие при преобразовании сущности class-файла. Вызывается до передачи любых элементов класса в accept(ClassFileBuilder, ClassFileElement).

Этот метод вызывается API файлов классов. Пользователям не следует вызывать этот метод.

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

andThen

C andThen(C next)
Объединяет это преобразование с другим; элементы, переданные построителю этого преобразования, станут входными данными для следующего преобразования.

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

Параметры:
next — последующее преобразование
Возвращает:
объединенное преобразование

Сообщить об ошибке или предложить улучшение
Дополнительные справочные материалы по 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/classfile/ClassFileTransform.html

Spec-Zone.ru

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