Отражение записей Java и синтетические методы

На основе более старых спецификаций языка Java (7) (13.1.7):

Любые конструкции, введенные компилятором Java, которые не имеют соответствующей конструкции в исходном коде, должны быть помечены как синтетические, за исключением конструкторов по умолчанию, метода инициализации класса и методов values ​​и valueOf класса Enum.

На более новых (Java (17) Language Specifications (13.1.7):) эта формулировка меняется на:

Конструкция, созданная компилятором Java, должна быть помечена как синтетическая, если она не соответствует конструкции, объявленной явно или неявно в исходном коде, если только созданная конструкция не является методом инициализации класса (JVMS §2.9).

Интересно, как это применимо к методам доступа, созданным для компонентов java Records (JEP 395)

Например

      record ARecord(int a){}

будет методint a()тем не менее, нет кода, представляющего такой метод, в соответствии с формулировкой более старого JLS такой метод добавляется компилятором, поэтому я ожидаю, что он будет синтетическим, но это не так, поскольку это можно подтвердить, выполнив следующие 2 строки наJShell

      jshell
|  Welcome to JShell -- Version 17.0.1
|  For an introduction type: /help intro

jshell> record ARecord(int a){}
|  created record ARecord

jshell> ARecord.class.getDeclaredMethod("a").isSynthetic();
$2 ==> false

jshell>

Причина, по которой я спрашиваю, заключается в том, что я хотел бы использовать отражение (или любое другое программное средство во время выполнения), чтобы определить, какие элементы в классе имеют совпадающую структуру кода, в основном те, у которых есть код, представляющий их, что означает:

Для следующего кода

      record ARecord(int a){

  pubic void someMethod() {}

}

эта сущность будет иметь 2 метода ( и ),aне имеет кода, представляющего его, иsomeMethodмне нужен способ различать те, которые основаны на этих критериях

1 ответ

Любые члены типа, имеющиеsyntheticфлаг полностью игнорируется. Javac ведет себя так, как будто этих вещей вообще не существует.

Как следствие, очевидно, что «добытчики», которые вы получаете за пластинку, не являются синтетическими. Если бы они были, было бы невозможно позвонить им из.javaкод - единственный способ вызвать их - это написать хакерскийjavacclone, который компилирует доступ к синтетике, или использовать манипуляции с байт-кодом для удаления синтетического флага, или напрямую выдавать байт-код, или использовать отражение.

Другие вопросы по тегам