src/share/classes/java/lang/reflect/AnnotatedElement.java

Print this page

        

@@ -25,10 +25,12 @@
 
 package java.lang.reflect;
 
 import java.lang.annotation.Annotation;
 import java.lang.annotation.AnnotationFormatError;
+import java.lang.annotation.Repeatable;
+import java.util.Objects;
 
 /**
  * Represents an annotated element of the program currently running in this
  * VM.  This interface allows annotations to be read reflectively.  All
  * annotations returned by methods in this interface are immutable and

@@ -220,36 +222,63 @@
      * annotation.
      *
      * The caller of this method is free to modify the returned array; it will
      * have no effect on the arrays returned to other callers.
      *
+     * @implSpec The default implementation first calls {@link
+     * #getAnnotation(Class)} on the argument type. If the annotation
+     * is directly or indirectly present, it is returned in an
+     * one-element array. Otherwise, if the argument annotation type
+     * is repeatable and an annotation of the container type is
+     * directly or indirectly present, then the returned result is
+     * equal to the result of calling the {@code value} method on the
+     * container annotation.
+     *
      * @param <T> the type of the annotation to query for and return if present
      * @param annotationClass the Class object corresponding to the
      *        annotation type
      * @return all this element's annotations for the specified annotation type if
      *     associated with this element, else an array of length zero
      * @throws NullPointerException if the given annotation class is null
      * @since 1.8
      */
-    <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass);
+    default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
+        return AnnotatedElementSupport.getAnnotationsByTypeDeclaredOrNot(this, annotationClass, false);
+    }
 
     /**
      * Returns this element's annotation for the specified type if
      * such an annotation is <em>directly present</em>, else null.
      *
      * This method ignores inherited annotations. (Returns null if no
      * annotations are directly present on this element.)
      *
+     * @implSpec The default implementation first performs a null check
+     * and then loops over the results of {@link
+     * getDeclaredAnnotations} returning the first annotation whose
+     * annotation type matches the argument type.
+     *
      * @param <T> the type of the annotation to query for and return if directly present
      * @param annotationClass the Class object corresponding to the
      *        annotation type
      * @return this element's annotation for the specified annotation type if
      *     directly present on this element, else null
      * @throws NullPointerException if the given annotation class is null
      * @since 1.8
      */
-    <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass);
+    default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) {
+        Objects.requireNonNull(annotationClass);
+        Annotation[] annotations =  getDeclaredAnnotations(); // All directly-present annotations
+        for (Annotation annotation : annotations) {
+            if (annotationClass.equals(annotation.annotationType())) {
+                // More robust to do a cast at runtime instead of
+                // compile-time only.
+                return annotationClass.cast(annotation);
+            }
+        }
+        return null; 
+    }
 
     /**
      * Returns this element's annotation(s) for the specified type if
      * such annotations are either <em>directly present</em> or
      * <em>indirectly present</em>. This method ignores inherited

@@ -266,20 +295,35 @@
      * through" a container annotation if one is present.
      *
      * The caller of this method is free to modify the returned array; it will
      * have no effect on the arrays returned to other callers.
      *
+     * @implSpec The default implementation may call {@link
+     * #getDeclaredAnnotation(Class)} one or more times to find a
+     * directly present annotation and, if the annotation type is
+     * repeatable, to find a container annotation. If the annotation
+     * type is both directly and indirectly present, {@link
+     * getDeclaredAnnotations()} will get called to determine the
+     * order of the elements in the returned array. Alternatively,
+     * {@link getDeclaredAnnotations()} may be called a single time
+     * and the returned array examined for both directly and
+     * indirectly present annotations. The results of calling {@link
+     * getDeclaredAnnotations()} are assumed to be consistent with the
+     * results of calling {@code #getDeclaredAnnotation}
+     *
      * @param <T> the type of the annotation to query for and return
      * if directly or indirectly present
      * @param annotationClass the Class object corresponding to the
      *        annotation type
      * @return all this element's annotations for the specified annotation type if
      *     directly or indirectly present on this element, else an array of length zero
      * @throws NullPointerException if the given annotation class is null
      * @since 1.8
      */
-    <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass);
+    default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) {
+        return AnnotatedElementSupport.getAnnotationsByTypeDeclaredOrNot(this, annotationClass, true);
+    }
 
     /**
      * Returns annotations that are <em>directly present</em> on this element.
      * This method ignores inherited annotations.
      *