Я разработал фреймворк и соответствующий API, который включает в себя видимую во время выполнения аннотацию.API также предоставляет некоторые вспомогательные методы, предназначенные для использования клиентом на объектах, классы которых имеют эту аннотацию.Понятно, что помощники тесно связаны с аннотацией, но важно, чтобы их внутренние компоненты были инкапсулированы от клиента.Вспомогательные методы в настоящее время предоставляются через статический внутренний класс внутри типа аннотации ...
@Target(TYPE)
@Retention(RUNTIME)
public @interface MyAnnotation {
// ... annotation elements, e.g. `int xyz();` ...
public static final class Introspection {
public static Foo helper(Object mightHaveMyAnnotation) {
/* ... uses MyAnnotation.xyz() if annotation is present ... */
}
}
}
... но помощники могут так же легко существовать в каком-либо другом служебном классе верхнего уровня.В любом случае обеспечивается необходимый объем инкапсуляции из клиентского кода, но оба несут дополнительные расходы на поддержание совершенно отдельного типа, предотвращают их создание, поскольку все полезные методы являются статическими и т. Д.
Когда Java 8 ввела статические методы вТипы интерфейса Java (см. JLS 9.4 ), эта функция рекламировалась как обеспечивающая возможность ...
... организовывать вспомогательные методы в ваших библиотеках;вы можете хранить статические методы, специфичные для интерфейса, в том же интерфейсе, а не в отдельном классе.
- из Java Tutorials Методы интерфейса по умолчанию
Это использовалось в библиотеках JDK для предоставления реализаций, таких как List.of(...)
, Set.of(...)
и т. Д., Тогда как ранее такие методы были отнесены к отдельному служебному классу, например java.util.Collections
.Размещая служебные методы в связанных с ними интерфейсах, он улучшает их обнаруживаемость и удаляет, возможно, ненужные типы вспомогательных классов из домена API.
Поскольку я являюсь текущей JVM представление байт-кода для типов аннотаций очень тесно связано с обычными интерфейсами , мне было интересно, будут ли аннотации также поддерживать статические методы.Когда я переместил помощников в тип аннотации, такой как:
@Target(TYPE)
@Retention(RUNTIME)
public @interface MyAnnotation {
// ... annotation elements ...
public static Foo helper(Object mightHaveMyAnnotation) { /* ... */ }
}
... Я был немного удивлен, что javac пожаловался на следующие ошибки во время компиляции:
Среда выполнения OpenJDK 18.3 (сборка 10 + 46)
- Статический модификатор здесь не разрешен
- элементы в объявлениях типа аннотации не могут объявлять формальные параметры
- интерфейс абстрактных методов не может иметь тела
Очевидно, что язык Java в настоящее время не позволяет этого.Возможно, существуют веские причины для его запрета или, как ранее предполагалось для статических методов интерфейса , «не было веских причин для этого; согласованность недостаточно убедительна для изменения статусаquo ".
В частности, , а не цель этого вопроса -" , почему не работает? "или " должен язык поддерживать его?", чтобы избежать основанных на мнении ответов.
JVM - это мощная технология, которая во многих отношениях более гибкая, чем то, что допускаетсяЯзык Java.В то же время язык Java продолжает развиваться, и сегодняшний ответ может устареть завтра.С пониманием того, что такая мощность должна использоваться с большой осторожностью ...
Технически возможно ли инкапсулировать статическое поведение непосредственно в типе аннотации и как?