JEP 118: Access to Parameter Names at Runtime
Доступ к именам параметров во время выполнения
| Автор | Joseph D. Darcy |
| Ответственный | Alex Buckley |
| Тип | Feature |
| Область | SE |
| Статус | Closed / Delivered |
| Выпуск | 8 |
| Компонент | specification / vm |
| JSRs | 269 MR, 337 |
| Обсуждение | enhanced dash metadata dash spec dash discuss at openjdk dot java dot net |
| Трудоёмкость | M |
| Длительность | M |
| Одобрен | Brian Goetz |
| Создан | 2011/10/18 20:00 |
| Обновлён | 2015/02/13 19:40 |
| Задача | 8046108 |
Аннотация
Предоставить механизм, позволяющий просто и надёжно получать имена параметров методов и конструкторов во время выполнения через core reflection.
Цели
Основная цель — сделать более читаемым код, который сейчас использует логически избыточные аннотации для записи имён параметров. Второстепенная цель — расширить возможности IDE за счёт того, что имена параметров станут доступны шире.
Мотивация
В Java используется позиционная передача параметров: первый аргумент вызова метода передаётся как первый параметр, второй аргумент — как второй параметр и так далее. Во многих других системах используется именованная передача параметров, при которой вместо этого передаётся что-то вроде набора пар имя:значение. Когда код на Java взаимодействует с системой именованной передачи параметров, для построения правильного соответствия имя:значение часто нужны имена параметров из исходного кода на Java. К сожалению, в существующих API Java SE нет надёжного способа получить имена параметров метода или конструктора. В качестве обходного решения различные API определили собственные аннотации «@ParameterName», из-за чего исходный код выглядит очень загромождённым.
IDE для Java уже сейчас умеют автоматически генерировать шаблонный код для создания конкретного подтипа интерфейса или абстрактного класса. Если исходный код доступен, в сгенерированном коде можно использовать имена параметров из исходного кода. Если бы информация об именах параметров надёжно хранилась в class-файлах, осмысленные имена можно было бы генерировать в большем числе случаев.
В зависимости от выбранного подхода может быть устранена и давняя проблема: невозможность определить, когда число параметров метода в исходном коде отличается от числа параметров в скомпилированной форме метода.
Описание
Предлагаемый подход — создать новый необязательный атрибут JVM в class-файлах версии 52.0 для хранения информации о параметрах метода на уровне JVM. Эта информация включает:
- имя параметра на уровне исходного кода, если оно есть;
- модификаторы параметра, если они есть.
Параметру метода или конструктора в class-файле может не соответствовать никакой параметр в исходном коде. Например,
-
В качестве решения на уровне реализации
javacдобавляет в начало списка параметров конструкторовenumдва синтетических параметра, чтобы компилятор мог передавать информацию об имени и порядковом номере. Другие компиляторы, включая реализацииjavacв других выпусках, вправе использовать иной способ реализации для передачи этой информации. -
В начало списка аргументов конструкторов анонимных внутренних классов обычно добавляется ещё один параметр, чтобы можно было передать информацию о внешнем this. Однако конструкторам анонимных внутренних классов в статическом контексте, например в блоке инициализации
static, такой параметр не нужен.
При наличии этой информации core reflection мог бы предоставить класс java.lang.reflect.Parameter для её получения. Метод, возвращающий массив объектов Parameter, был бы определён в java.lang.reflect.Executable — общем суперклассе Method и Constructor. Более прямое моделирование информации о параметрах предпочтительнее, чем продолжение косвенного моделирования, как в Method.getParameterTypes и Method.getParameterAnnotations, где поведение синтетических параметров чётко не определено.
Чтобы не вводить лишних ограничений совместимости, следует различать имена параметров, доступные только в информационных целях, и имена параметров, которые предоставляются как публичный интерфейс метода или конструктора. Аннотация — хороший кандидат для краткого указания того, служат ли конкретные имена параметров экспортируемым интерфейсом.
Альтернативы
Дизайн не окончательный, но среди альтернатив — хранение информации об именах в аннотациях параметров, синтезируемых компилятором. Признаком того, что такие аннотации параметров нужно синтезировать, могло бы служить наличие аннотации на классе или интерфейсе или даже метааннотации на типе аннотации, найденной на классе или интерфейсе.
Тестирование
Если исходить из общего подхода, изложенного в разделе «Описание», большая часть реализации относилась бы к области во многом неявной спецификации компилятора, то есть спецификации того, как компилятор Java транслирует исходный код на Java в class-файлы (или другой исполняемый формат вывода). Поскольку тестируется соответствие между исходным кодом и class-файлом, это естественным образом совпадает с областями покрытия тестов JCK, но для покрытия в рамках JCK нужна некая определяющая спецификация Java SE.
Для конкретного дизайна сравнительно просто использовать обработчики аннотаций, чтобы генерировать различные примеры кода, охватывающие всё пространство тестируемых переменных.
Риски и допущения
Из-за введения нового атрибута JVM затраты на согласование этого изменения значительно возрастают, поскольку инструменты, работающие с class-файлами, от pack200 до самой JVM, нужно обновить, чтобы они правильно обрабатывали новый атрибут.
Поддержка со стороны нескольких IDE во время разработки JDK 8 помогла бы проверить работу этой возможности.
Зависимости
Среди компонентов JDK полная реализация этой возможности требует согласованных изменений в компиляторе, библиотеках и JVM.
Влияние
- Совместимость: по умолчанию имена параметров не должны становиться частью обязательств метода или конструктора по совместимости.
- Производительность и масштабируемость: следует отслеживать производительность
javac, чтобы убедиться, что не возникает снижения производительности.