Is it possible to make annotations be applicable to fields of a specific type?

2.7k Views Asked by At

For instance, in the follwing annotation:

@Target(ElementType.FIELD) 
@Retention(RetentionPolicy.RUNTIME)
public @interface EndOfTheCurrentDay {
    //some staff
}

it is obviously that we can't apply the annotation to the field of the type, say, Integer. But in the way it was implemented, the usage of the annotation may be unsafe. How can I prevet applying the annotaion to the field other than java.util.Date? Is it even posible?

3

There are 3 best solutions below

6
On

No, you cannot reliably restrict this and generate errors during compilation - annotation processors can be disabled. If you want to be absolutely certain you need to validate it in runtime when you process the annotation:

void processAnnotations(Field f) {
    EndOfTheCurrentDay annotation = f.getAnnotation(EndOfTheCurrentDay.class);
    if(annotation == null) {
        return; // Nothing to do
    }
    if(Date.class.isAssignableFrom(f.getType())) {
        throw new Error("The @EndOfTheCurrentDay annotation may only be applied to fields of type Date");
    }
    // Do something with the field
}
0
On

Yes, you can cause the compiler to issue an error message if you write the annotation on a field of the wrong type.

You cannot do this through the standard @Target meta-annotation. Instead, you need to write an annotation processor. The annotation processor will examine each occurrence of the annotation @EndOfTheCurrentDay in your source code, and it issues an error (just like any other compiler error) if @EndOfTheCurrentDay is applied to a non-Date type. This is a short, simple annotation processor to write.

You will only get the compile-time warning when running the annotation processor, but you can add the -processor ... command-line argument to javac in your project's buildfile.

0
On

write an annotation processor:

@SupportedAnnotationTypes("org.example.EndOfTheCurrentDay")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class EndOfDayAnnotationsProcessor extends AbstractProcessor
{

    @Override
    public boolean process(
            Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv)
    {
        for (Element element : roundEnv.getElementsAnnotatedWith(annotations.iterator().next()))
        {
            if(!element.asType().toString().equals(Date.class.getName())){
                processingEnv.getMessager().printMessage(ERROR,"annotation @EndOfTheCurrentDay can only be applied to java.util.Date!",element);
            }
        }
        return true;
    }

}

and register in META-INF/services/javax.annotation.processing.Processor