I have a Java package that contains annotations used by external clients. The package appeared before Java 8, so historically these annotations have targets ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE
. Now the package requires at least Java 8 version. Semantically the annotations in the package are applicable to the types, so e.g. when the method is annotated, the annotation effectively applies to the method return type. Now clients want to annotate generic type arguments as well (e.g. List<@MyAnnotation String>
). Since we dropped the support of Java 7 and below, it seems quite natural to set the annotation target to ElementType.TYPE_USE
and, to reduce ambiguity, remove the existing targets.
Here's the question: are there any compatibility risks for existing clients when replacing ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE
targets with TYPE_USE
? Is it possible that the existing code will stop compiling? What about binary compatibility? May it cause any runtime problems if the class-files compiled before the change are used together with newer annotations pack at runtime?
Annotations' retention policy is CLASS
if this matters.
There are a number of source compatibility issues that may arise during this change:
void
return type cannot be annotated anymore. @MyAnnotation void method() {}
is compilable with ElementType.METHOD
target but not compilable with TYPE_USE
target.TYPE_USE
annotation must appear after the qualifier. E.g. void method(@MyAnnotation OuterClass.InnerClass param) {}
is a valid code with ElementType.PARAMETER
target, but should be updated to void method(OuterClass.@MyAnnotation InnerClass param) {}
after changing to TYPE_USE
.@MyAnnotation String[] getData();
annotates the method getData
, so the annotation clients likely assume that annotation is applied to the return type (an array of strings). After the migration, the same code means that the annotation is applied to the array component (string). This might cause a behavioral change, depending on the annotation semantics and how it's processed by clients. To preserve the meaning, clients should update such a code to String @MyAnnotation [] getData();
.TYPE_USE
annotations and others. E.g. a PARAMETER
annotation must be used as fun(@MyAnnotation param : String) {...}
. This is incorrect for TYPE_USE
annotation, which must be used as fun(param : @MyAnnotation String) {...}
. If your clients use Kotlin they will have to fix every single annotation use.No problems should arise at runtime though. As annotations' retention policy is CLASS
(not RUNTIME
), while the annotations present in class files they are ignored by the runtime. It's not necessary to add your annotation pack to the classpath at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With