I have an annotation used for methods or fields defined like this:
@Retention(RetentionPolicy.RUNTIME) @Target(value = {ElementType.METHOD, ElementType.FIELD}) public @interface NotColumn { }
I wanted to prevent users from using this on a record since it wouldn’t make sense for this annotation to be used in that context. It seems doing this should not compile since I don’t specify ElementType.PARAMETER
as a valid @Target
.
The following compiles fine though:
public record MyRecord(String customerId, String companyName, @NotColumn String description }
But this form with a compact constructor fails to compile with “java: annotation type not applicable to this kind of declaration” – which is actually what I would expect.
public record MyRecord(String customerId, String companyName, @NotColumn String description public MyRecord { } }
Advertisement
Answer
public record MyRecord(String customerId, String companyName, @NotColumn String description
description
may look a bit like a parameter but for the purpose of annotation targeting, it’s not strictly just that. It can act like a field too.
From the JLS (this version has highlighted the parts which have changed with respect to records):
Annotations on a record component of a record class may be propagated to members and constructors of the record class as specified in 8.10.3.
The gist of section 8.10.3 is that annotations such as your @NotColumn
are propagated onto the generated methods, fields and parameters only if they are applicable to those targets. They are ignored otherwise. Your annotation is applicable to fields, so it will be propagated to the generated description
field of the record.
The fact that you get an error when adding a constructor is a bug and has been fixed already. The validity of the annotation was supposed to be the same whether you specify a constructor or not. In future versions of Java, both of your examples will compile fine.
I wanted to prevent users from using this [annotation] on a record
It’s not possible, sorry.