0

I have a repeatable annotation with a Class type attribute like this one.

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.PARAMETER)
public @interface MyAnnotation {
    Class<?> value();
}

I'm trying to get the class name from it using AnnotationMirrors since I can't grab the class directly without getting a MirroredTypeException. This is the same as this question except that this annotation is repeatable, meaning it's wrapped in another annotation like this one.

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.PARAMETER)
public @interface MyAnnotationWrapper {
    MyAnnotation[] value();
}

I can only figure out how to get the mirror for the wrapper annotation and not the repeatable one. I was able to accomplish what I needed using the hacky workaround in the linked question in combination with invoking the annotation method via reflection and grabbing the cause from the exception I got. It looked something like this (I don't have the code in front of me right now).

try {
  annotation.getClass().getMethod("value").invoke(annotation)
} catch (<Several exception types> e) {
  className = ((MirroredTypeException) e.getCause()).getTypeMirror().toString()
}

I want to know if there's a correct way to get the class name in this case.

rybai
  • 53
  • 4

1 Answers1

0

Catch and use getTypeMirror does be the correct way.

You can use my utility method to get the TypeMirror by method invoke rather than reflect with string.

  /**
   * For Class attribute, if we invoke directly, it may throw {@link MirroredTypeException} because the class has not be
   * compiled. Use this method to get the Class value safely.
   *
   * @param elements Elements for convert Class to TypeMirror
   * @param anno annotation object
   * @param func the invocation of get Class value
   * @return the value's {@link TypeMirror}
   */
  public static <T extends Annotation> TypeMirror getAnnotationClassValue(Elements elements, T anno,
      Function<T, Class<?>> func) {
    try {
      return elements.getTypeElement(func.apply(anno).getCanonicalName()).asType();
    } catch (MirroredTypeException e) {
      return e.getTypeMirror();
    }
  }

Usage

  getAnnotationClassValue(elements, annotation, MyAnnotation::value)

And for you repeate wrapper, you should get the array value and get TypeMirror one by one.

Dean Xu
  • 4,438
  • 1
  • 17
  • 44