Skip to content

What annotation targets are applicable to Java records?

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 {
   }
}

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.