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.
*