Каковы риски совместимости замены МЕТОД / ПОЛЕ / et c. цели с TYPE_USE - PullRequest
6 голосов
/ 30 января 2020

У меня есть пакет Java, который содержит аннотации, используемые внешними клиентами. Пакет появился до Java 8, поэтому исторически эти аннотации имеют цели ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE. Теперь пакет требует как минимум Java 8 версию. Семантически аннотации в пакете применимы к типам, поэтому, например, когда метод аннотирован, аннотация эффективно применяется к типу возврата метода. Теперь клиенты хотят также аннотировать аргументы типа c (например, List<@MyAnnotation String>). Поскольку мы опустили поддержку Java 7 и ниже, кажется вполне естественным установить цель аннотации на ElementType.TYPE_USE и, чтобы уменьшить двусмысленность, удалить существующие цели.

Вот вопрос: есть ли риски совместимости для существующих клиентов при замене ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE целей на TYPE_USE? Возможно ли, что существующий код перестанет компилироваться? Как насчет двоичной совместимости? Может ли это вызвать какие-либо проблемы во время выполнения, если файлы классов, скомпилированные до изменения, используются вместе с более новым пакетом аннотаций во время выполнения?

Политика хранения аннотаций CLASS, если это имеет значение.

1 Ответ

7 голосов
/ 30 января 2020

Во время этого изменения может возникнуть ряд проблем совместимости с источником:

  • Методы с void типом возврата больше не могут быть аннотированы. @MyAnnotation void method() {} компилируется с ElementType.METHOD target, но не компилируется с TYPE_USE target.
  • Когда в исходном коде используется квалифицированный тип, после квалификатора должна появляться аннотация TYPE_USE. Например, void method(@MyAnnotation OuterClass.InnerClass param) {} является допустимым кодом с ElementType.PARAMETER target, но его следует обновить до void method(OuterClass.@MyAnnotation InnerClass param) {} после изменения на TYPE_USE.
  • Аннотация, примененная к массивам, будет иметь другое значение. Например, перед миграцией @MyAnnotation String[] getData(); аннотирует метод getData, поэтому клиенты аннотаций, вероятно, предполагают, что аннотация применяется к возвращаемому типу (массиву строк). После миграции тот же код означает, что аннотация применяется к компоненту массива (строка). Это может вызвать изменение поведения в зависимости от семантики аннотации и способа ее обработки клиентами. Чтобы сохранить значение, клиенты должны обновить такой код до String @MyAnnotation [] getData();.
  • . Такое изменение делает все использования аннотаций в коде Kotlin недействительными. В Kotlin существует строго синтаксическая разница между TYPE_USE аннотациями и другими. Например, аннотация PARAMETER должна использоваться как fun(@MyAnnotation param : String) {...}. Это неверно для аннотации TYPE_USE, которая должна использоваться как fun(param : @MyAnnotation String) {...}. Если ваши клиенты используют Kotlin, им придется исправлять каждое использование аннотаций.
  • Такое изменение не позволяет использовать ваши аннотации в коде Groovy. В настоящее время, как говорится в Groovy документации , Groovy не поддерживает типы элементов TYPE_PARAMETER и TYPE_USE, представленные в Java 8. Если ваши клиенты используют Groovy, они не смогут больше используйте свой пакет аннотаций.

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

...