diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index dab6c98e47a..671d04a65c7 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -3087,7 +3087,8 @@ public final * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public A[] getAnnotations(Class annotationClass) { + @Override + public A[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); @@ -3106,6 +3107,7 @@ public final * @throws NullPointerException {@inheritDoc} * @since 1.8 */ + @Override @SuppressWarnings("unchecked") public A getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); @@ -3118,7 +3120,8 @@ public final * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public A[] getDeclaredAnnotations(Class annotationClass) { + @Override + public A[] getDeclaredAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); initAnnotationsIfNecessary(); diff --git a/jdk/src/share/classes/java/lang/Package.java b/jdk/src/share/classes/java/lang/Package.java index 234f807181a..b9776f478db 100644 --- a/jdk/src/share/classes/java/lang/Package.java +++ b/jdk/src/share/classes/java/lang/Package.java @@ -389,8 +389,9 @@ public class Package implements java.lang.reflect.AnnotatedElement { * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public A[] getAnnotations(Class annotationClass) { - return getPackageInfo().getAnnotations(annotationClass); + @Override + public A[] getAnnotationsByType(Class annotationClass) { + return getPackageInfo().getAnnotationsByType(annotationClass); } /** @@ -404,6 +405,7 @@ public class Package implements java.lang.reflect.AnnotatedElement { * @throws NullPointerException {@inheritDoc} * @since 1.8 */ + @Override public A getDeclaredAnnotation(Class annotationClass) { return getPackageInfo().getDeclaredAnnotation(annotationClass); } @@ -412,8 +414,9 @@ public class Package implements java.lang.reflect.AnnotatedElement { * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public A[] getDeclaredAnnotations(Class annotationClass) { - return getPackageInfo().getDeclaredAnnotations(annotationClass); + @Override + public A[] getDeclaredAnnotationsByType(Class annotationClass) { + return getPackageInfo().getDeclaredAnnotationsByType(annotationClass); } /** diff --git a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java index 9986aef6cf7..d198d939d4b 100644 --- a/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java +++ b/jdk/src/share/classes/java/lang/reflect/AccessibleObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -184,7 +184,8 @@ public class AccessibleObject implements AnnotatedElement { * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { throw new AssertionError("All subclasses should override this method"); } @@ -199,6 +200,7 @@ public class AccessibleObject implements AnnotatedElement { * @throws NullPointerException {@inheritDoc} * @since 1.8 */ + @Override public T getDeclaredAnnotation(Class annotationClass) { // Only annotations on classes are inherited, for all other // objects getDeclaredAnnotation is the same as @@ -210,11 +212,12 @@ public class AccessibleObject implements AnnotatedElement { * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public T[] getDeclaredAnnotations(Class annotationClass) { + @Override + public T[] getDeclaredAnnotationsByType(Class annotationClass) { // Only annotations on classes are inherited, for all other - // objects getDeclaredAnnotations is the same as - // getAnnotations. - return getAnnotations(annotationClass); + // objects getDeclaredAnnotationsByType is the same as + // getAnnotationsByType. + return getAnnotationsByType(annotationClass); } /** diff --git a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java index 85472ff5b00..d6cffec2f28 100644 --- a/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java +++ b/jdk/src/share/classes/java/lang/reflect/AnnotatedElement.java @@ -35,22 +35,43 @@ import java.lang.annotation.Annotation; * arrays returned by accessors for array-valued enum members; it will * have no affect on the arrays returned to other callers. * - *

An annotation A is directly present on an element E if the - * RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute - * associated with E either: + *

The {@link #getAnnotationsByType(Class)} and {@link + * #getDeclaredAnnotationsByType(Class)} methods support multiple + * annotations of the same type on an element. If the argument to either method + * is a repeatable annotation type (JLS 9.6), then the method will "look + * through" a container annotation (JLS 9.7) which was generated at + * compile-time to wrap multiple annotations of the argument type. + * + *

The terms directly present and present are used + * throughout this interface to describe precisely which annotations are + * returned by methods: + * *

    - *
  • contains A; or - *
  • for invocations of get[Declared]Annotations(Class), - * contains A or exactly one annotation C whose type is the containing - * annotation type of A's type (JLS 9.6) and whose value element contains A + *
  • An annotation A is directly present on an element E if E is + * associated with a RuntimeVisibleAnnotations or + * RuntimeVisibleParameterAnnotations attribute, and: + * + *
      + *
    • for an invocation of {@code get[Declared]Annotation(Class)} or + * {@code get[Declared]Annotations()}, the attribute contains A. + * + *
    • for an invocation of {@code get[Declared]AnnotationsByType(Class)}, the + * attribute either contains A or, if the type of A is repeatable, contains + * exactly one annotation whose value element contains A and whose type is the + * containing annotation type of A's type (JLS 9.6). *
    * - *

    An annotation A is present on an element E if either: + *

    + *

  • An annotation A is present on an element E if either: + * *
      *
    • A is directly present on E; or - *
    • There are no annotations of A's type which are directly present - * on E, and E is a class, and A's type is inheritable (JLS 9.6.3.3), and A is - * present on the superclass of E + * + *
    • A is not directly present on E, and E is a class, and A's type + * is inheritable (JLS 9.6.3.3), and A is present on the superclass of + * E. + *
    + * *
* *

If an annotation returned by a method in this interface contains @@ -119,12 +140,19 @@ public interface AnnotatedElement { T getAnnotation(Class annotationClass); /** - * Returns an array of all this element's annotations for the - * specified type if one or more of such annotation is present, - * else an array of length zero. + * Returns annotations that are present on this element. * - * The caller of this method is free to modify the returned array; - * it will have no effect on the arrays returned to other callers. + * If there are no annotations present on this element, the return + * value is an array of length 0. + * + * The difference between this method and {@link #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. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. * * @param annotationClass the Class object corresponding to the * annotation type @@ -133,7 +161,7 @@ public interface AnnotatedElement { * @throws NullPointerException if the given annotation class is null * @since 1.8 */ - T[] getAnnotations(Class annotationClass); + T[] getAnnotationsByType(Class annotationClass); /** * Returns annotations that are present on this element. @@ -165,16 +193,21 @@ public interface AnnotatedElement { */ T getDeclaredAnnotation(Class annotationClass); - /** - * Returns an array of all this element's annotations for the - * specified type if one or more of such annotation is directly - * present, else an array of length zero. + /** + * Returns annotations that are directly present on this element. + * This method ignores inherited annotations. * - * This method ignores inherited annotations. (Returns - * an array of length zero if no annotations are directly present - * on this element.) The caller of this method is free to modify - * the returned array; it will have no effect on the arrays - * returned to other callers. + * If there are no annotations directly present on this element, + * the return value is an array of length 0. + * + * The difference between this method and {@link + * #getDeclaredAnnotation(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. + * + * The caller of this method is free to modify the returned array; it will + * have no effect on the arrays returned to other callers. * * @param annotationClass the Class object corresponding to the * annotation type @@ -183,7 +216,7 @@ public interface AnnotatedElement { * @throws NullPointerException if the given annotation class is null * @since 1.8 */ - T[] getDeclaredAnnotations(Class annotationClass); + T[] getDeclaredAnnotationsByType(Class annotationClass); /** * Returns annotations that are directly present on this element. diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index 4c785e3e87f..83b5e9c87a4 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -449,7 +449,8 @@ public abstract class Executable extends AccessibleObject * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); diff --git a/jdk/src/share/classes/java/lang/reflect/Field.java b/jdk/src/share/classes/java/lang/reflect/Field.java index df38832eb15..be13b076832 100644 --- a/jdk/src/share/classes/java/lang/reflect/Field.java +++ b/jdk/src/share/classes/java/lang/reflect/Field.java @@ -1029,7 +1029,8 @@ class Field extends AccessibleObject implements Member { * @throws NullPointerException {@inheritDoc} * @since 1.8 */ - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); diff --git a/jdk/src/share/classes/java/lang/reflect/Parameter.java b/jdk/src/share/classes/java/lang/reflect/Parameter.java index 3ecd7c674ea..9c808310c0c 100644 --- a/jdk/src/share/classes/java/lang/reflect/Parameter.java +++ b/jdk/src/share/classes/java/lang/reflect/Parameter.java @@ -258,7 +258,8 @@ public final class Parameter implements AnnotatedElement { * {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getMultipleAnnotations(declaredAnnotations(), annotationClass); @@ -284,11 +285,12 @@ public final class Parameter implements AnnotatedElement { /** * @throws NullPointerException {@inheritDoc} */ - public T[] getDeclaredAnnotations(Class annotationClass) { + @Override + public T[] getDeclaredAnnotationsByType(Class annotationClass) { // Only annotations on classes are inherited, for all other // objects getDeclaredAnnotations is the same as // getAnnotations. - return getAnnotations(annotationClass); + return getAnnotationsByType(annotationClass); } /** diff --git a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java index e0524e849dc..e9f3f957c09 100644 --- a/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java +++ b/jdk/src/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java @@ -148,8 +148,8 @@ public class AnnotatedTypeFactory { } @Override - public final T[] getAnnotations(Class annotation) { - return getDeclaredAnnotations(annotation); + public final T[] getAnnotationsByType(Class annotation) { + return getDeclaredAnnotationsByType(annotation); } @Override @@ -164,7 +164,7 @@ public class AnnotatedTypeFactory { } @Override - public T[] getDeclaredAnnotations(Class annotation) { + public T[] getDeclaredAnnotationsByType(Class annotation) { return AnnotationSupport.getMultipleAnnotations(annotations, annotation); } diff --git a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java index 528658d0d16..0b1a13ee74e 100644 --- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java +++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java @@ -200,14 +200,16 @@ public class TypeVariableImpl return getAnnotation(annotationClass); } - public T[] getAnnotations(Class annotationClass) { + @Override + public T[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); return AnnotationSupport.getMultipleAnnotations(mapAnnotations(getAnnotations()), annotationClass); } - public T[] getDeclaredAnnotations(Class annotationClass) { + @Override + public T[] getDeclaredAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - return getAnnotations(annotationClass); + return getAnnotationsByType(annotationClass); } public Annotation[] getAnnotations() { diff --git a/jdk/test/java/lang/annotation/TypeParamAnnotation.java b/jdk/test/java/lang/annotation/TypeParamAnnotation.java index 50457ec46b1..694d83dcd35 100644 --- a/jdk/test/java/lang/annotation/TypeParamAnnotation.java +++ b/jdk/test/java/lang/annotation/TypeParamAnnotation.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8004698 + * @bug 8004698 8007278 * @summary Unit test for annotations on TypeVariables */ @@ -93,7 +93,7 @@ public class TypeParamAnnotation { private static void testGetAnnos() throws Exception { TypeVariable[] ts = TypeParam.class.getDeclaredMethod("foo").getTypeParameters(); ParamAnno2[] as; - as = ts[0].getAnnotations(ParamAnno2.class); + as = ts[0].getAnnotationsByType(ParamAnno2.class); check(as.length == 1); check(as[0].value() == 3); } diff --git a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java index 10e3d746261..674f37fbb56 100644 --- a/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java +++ b/jdk/test/java/lang/annotation/repeatingAnnotations/RepeatedUnitTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7154390 8005712 + * @bug 7154390 8005712 8007278 * @summary Unit test for repeated annotation reflection * * @compile RepeatedUnitTest.java subpackage/package-info.java subpackage/Container.java subpackage/Containee.java subpackage/NonRepeated.java subpackage/InheritedContainee.java subpackage/InheritedContainer.java subpackage/InheritedNonRepeated.java @@ -76,7 +76,7 @@ public class RepeatedUnitTest { check(1 == countAnnotation(e, NonRepeated.class)); - nr = e.getAnnotations(NonRepeated.class)[0]; + nr = e.getAnnotationsByType(NonRepeated.class)[0]; check(nr.value() == 10); check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class)); @@ -87,9 +87,9 @@ public class RepeatedUnitTest { check(c == null); check(2 == countAnnotation(e, Containee.class)); - c = e.getAnnotations(Containee.class)[0]; + c = e.getAnnotationsByType(Containee.class)[0]; check(c.value() == 1); - c = e.getAnnotations(Containee.class)[1]; + c = e.getAnnotationsByType(Containee.class)[1]; check(c.value() == 2); check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); @@ -98,7 +98,7 @@ public class RepeatedUnitTest { static void packageContainer(AnnotatedElement e) { Container cr = e.getAnnotation(Container.class); check(null != cr); - check(1 == containsAnnotationOfType(e.getAnnotations(Container.class), Container.class)); + check(1 == containsAnnotationOfType(e.getAnnotationsByType(Container.class), Container.class)); check(1 == countAnnotation(e, Container.class)); } @@ -123,10 +123,10 @@ public class RepeatedUnitTest { check(1 == countAnnotation(e, NonRepeated.class)); check(1 == countAnnotation(e, InheritedNonRepeated.class)); - check(e.getAnnotations(Containee.class)[2].value() == 300); - check(e.getAnnotations(InheritedContainee.class)[2].value() == 300); - check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 200); - check(e.getAnnotations(NonRepeated.class)[0].value() == 100); + check(e.getAnnotationsByType(Containee.class)[2].value() == 300); + check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 300); + check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 200); + check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 100); } static void inheritedMe3() { @@ -138,8 +138,8 @@ public class RepeatedUnitTest { check(0 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, InheritedContainer.class)); - check(e.getAnnotations(InheritedContainee.class)[2].value() == 350); - check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 15); + check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 350); + check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 15); } static void inheritedMe4() { @@ -153,24 +153,24 @@ public class RepeatedUnitTest { check(1 == countAnnotation(e, NonRepeated.class)); check(1 == countAnnotation(e, InheritedNonRepeated.class)); - check(e.getAnnotations(Containee.class)[2].value() == 3000); - check(e.getAnnotations(InheritedContainee.class)[2].value() == 3000); - check(e.getAnnotations(InheritedNonRepeated.class)[0].value() == 2000); - check(e.getAnnotations(NonRepeated.class)[0].value() == 1000); + check(e.getAnnotationsByType(Containee.class)[2].value() == 3000); + check(e.getAnnotationsByType(InheritedContainee.class)[2].value() == 3000); + check(e.getAnnotationsByType(InheritedNonRepeated.class)[0].value() == 2000); + check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 1000); } static void checkMultiplier(AnnotatedElement e, int m) { // Basic sanity of non-repeating getAnnotation(Class) check(e.getAnnotation(NonRepeated.class).value() == 5 * m); - // Check count of annotations returned from getAnnotations(Class) + // Check count of annotations returned from getAnnotationsByType(Class) check(4 == countAnnotation(e, Containee.class)); check(1 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, NonRepeated.class)); - // Check contents of array returned from getAnnotations(Class) - check(e.getAnnotations(Containee.class)[2].value() == 3 * m); - check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m); + // Check contents of array returned from getAnnotationsByType(Class) + check(e.getAnnotationsByType(Containee.class)[2].value() == 3 * m); + check(e.getAnnotationsByType(NonRepeated.class)[0].value() == 5 * m); // Check getAnnotation(Class) check(e.getAnnotation(Containee.class) == null); @@ -187,7 +187,7 @@ public class RepeatedUnitTest { } static int countAnnotation(AnnotatedElement e, Class c) { - return containsAnnotationOfType(e.getAnnotations(c), c); + return containsAnnotationOfType(e.getAnnotationsByType(c), c); } static int containsAnnotationOfType(A[] l, Class a) {