Dims
Dims

Reputation: 51039

Same type multiple annotations in compatible way for case N = 1

Java 8 allows multiple annotations of the same type on same element with the help of @Repeatable annotation.

Unfortunately, they apparently forgot corresponding feature supporting for the case of one annotation:

import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;

public class MultipleAnnotationsCompatibility {

   @Inherited
   @Retention(RetentionPolicy.RUNTIME)
   public @interface FileTypes {
      FileType[] value();
   }

   @Inherited
   @Repeatable(FileTypes.class)
   @Retention(RetentionPolicy.RUNTIME)
   public @interface FileType {
      String value();
   }

   @FileType("png")
   @FileType("jpg")
   public static class Image {
   }

   @FileType("xls")
   public static class Worksheet {
   }

   public static void main(String[] args) {

      FileTypes fileTypes;

      fileTypes = Image.class.getAnnotation(FileTypes.class);

      System.out.println("fileTypes for Image = " + Objects.toString(fileTypes));

      fileTypes = Worksheet.class.getAnnotation(FileTypes.class);

      System.out.println("fileTypes for Worksheet = " + Objects.toString(fileTypes));

   }

}

The second println outputs null despite the fact, that there is no logical difference between the cases.

Is there any way to process the cases of 1 and 2+ annotations with the same code?

They should probably make boolean parameter for @Repeatable to treat singlecase annotations in the same way?

Upvotes: 2

Views: 205

Answers (1)

assylias
assylias

Reputation: 328618

You can use Class::getAnnotationsByType in both cases:

The difference between this method and AnnotatedElement.getAnnotation(Class) is that this method detects if its argument is a repeatable annotation type (JLS 9.6), and if so, attempts to find one or more annotations of that type by "looking through" a container annotation.

Revised example:

FileType[] fileTypes;

fileTypes = Image.class.getAnnotationsByType(FileType.class);
System.out.println("fileTypes for Image = " + Arrays.toString(fileTypes));

fileTypes = Worksheet.class.getAnnotationsByType(FileType.class);
System.out.println("fileTypes for Worksheet = " + Arrays.toString(fileTypes));

Outputs:

fileTypes for Image = [@abc$FileType(value=png), @abc$FileType(value=jpg)]
fileTypes for Worksheet = [@abc$FileType(value=xls)]

Upvotes: 5

Related Questions