提交 5b5bfe29 编写于 作者: J jfranck

8005712: Simplify support for repeating annotations in j.l.r.AnnotatedElement

8004919: AnnotationSupport uses possibly half-constructed AnnotationType instances
Summary: Implements the simplified semantics for repeating annotations and removes the incorrect obtaining of an AnnotationType
Reviewed-by: darcy, abuckley
上级 6f3e485f
...@@ -3075,11 +3075,12 @@ public final ...@@ -3075,11 +3075,12 @@ public final
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @since 1.5 * @since 1.5
*/ */
@SuppressWarnings("unchecked")
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) { public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary(); initAnnotationsIfNecessary();
return AnnotationSupport.getOneAnnotation(annotations, annotationClass); return (A) annotations.get(annotationClass);
} }
/** /**
...@@ -3108,18 +3109,19 @@ public final ...@@ -3108,18 +3109,19 @@ public final
*/ */
public Annotation[] getAnnotations() { public Annotation[] getAnnotations() {
initAnnotationsIfNecessary(); initAnnotationsIfNecessary();
return AnnotationSupport.unpackToArray(annotations); return AnnotationParser.toArray(annotations);
} }
/** /**
* @throws NullPointerException {@inheritDoc} * @throws NullPointerException {@inheritDoc}
* @since 1.8 * @since 1.8
*/ */
@SuppressWarnings("unchecked")
public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) { public <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary(); initAnnotationsIfNecessary();
return AnnotationSupport.getOneAnnotation(declaredAnnotations, annotationClass); return (A) declaredAnnotations.get(annotationClass);
} }
/** /**
...@@ -3138,17 +3140,7 @@ public final ...@@ -3138,17 +3140,7 @@ public final
*/ */
public Annotation[] getDeclaredAnnotations() { public Annotation[] getDeclaredAnnotations() {
initAnnotationsIfNecessary(); initAnnotationsIfNecessary();
return AnnotationSupport.unpackToArray(declaredAnnotations); return AnnotationParser.toArray(declaredAnnotations);
}
/** Returns one "directly" present annotation or null */
<A extends Annotation> A getDirectDeclaredAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
initAnnotationsIfNecessary();
@SuppressWarnings("unchecked") // TODO check safe
A ret = (A)declaredAnnotations.get(annotationClass);
return ret;
} }
// Annotations cache // Annotations cache
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
package java.lang; package java.lang;
import java.io.*; import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Executable; import java.lang.reflect.Executable;
import java.util.Properties; import java.util.Properties;
import java.util.PropertyPermission; import java.util.PropertyPermission;
...@@ -1197,9 +1196,6 @@ public final class System { ...@@ -1197,9 +1196,6 @@ public final class System {
public AnnotationType getAnnotationType(Class<?> klass) { public AnnotationType getAnnotationType(Class<?> klass) {
return klass.getAnnotationType(); return klass.getAnnotationType();
} }
public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno) {
return klass.getDirectDeclaredAnnotation(anno);
}
public byte[] getRawClassTypeAnnotations(Class<?> klass) { public byte[] getRawClassTypeAnnotations(Class<?> klass) {
return klass.getRawTypeAnnotations(); return klass.getRawTypeAnnotations();
} }
......
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -35,6 +35,24 @@ import java.lang.annotation.Annotation; ...@@ -35,6 +35,24 @@ import java.lang.annotation.Annotation;
* arrays returned by accessors for array-valued enum members; it will * arrays returned by accessors for array-valued enum members; it will
* have no affect on the arrays returned to other callers. * have no affect on the arrays returned to other callers.
* *
* <p>An annotation A is <em>directly present</em> on an element E if the
* RuntimeVisibleAnnotations or RuntimeVisibleParameterAnnotations attribute
* associated with E either:
* <ul>
* <li>contains A; or
* <li>for invocations of get[Declared]Annotations(Class<T>),
* 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
* </ul>
*
* <p>An annotation A is <em>present</em> on an element E if either:
* <ul>
* <li>A is <em>directly present</em> on E; or
* <li>There are no annotations of A's type which are <em>directly present</em>
* 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
* </ul>
*
* <p>If an annotation returned by a method in this interface contains * <p>If an annotation returned by a method in this interface contains
* (directly or indirectly) a {@link Class}-valued member referring to * (directly or indirectly) a {@link Class}-valued member referring to
* a class that is not accessible in this VM, attempting to read the class * a class that is not accessible in this VM, attempting to read the class
...@@ -50,7 +68,7 @@ import java.lang.annotation.Annotation; ...@@ -50,7 +68,7 @@ import java.lang.annotation.Annotation;
* containing annotation type of T will result in an * containing annotation type of T will result in an
* InvalidContainerAnnotationError. * InvalidContainerAnnotationError.
* *
* <p>Finally, Attempting to read a member whose definition has evolved * <p>Finally, attempting to read a member whose definition has evolved
* incompatibly will result in a {@link * incompatibly will result in a {@link
* java.lang.annotation.AnnotationTypeMismatchException} or an * java.lang.annotation.AnnotationTypeMismatchException} or an
* {@link java.lang.annotation.IncompleteAnnotationException}. * {@link java.lang.annotation.IncompleteAnnotationException}.
...@@ -70,6 +88,9 @@ public interface AnnotatedElement { ...@@ -70,6 +88,9 @@ public interface AnnotatedElement {
* is present on this element, else false. This method * is present on this element, else false. This method
* is designed primarily for convenient access to marker annotations. * is designed primarily for convenient access to marker annotations.
* *
* <p>The truth value returned by this method is equivalent to:
* {@code getAnnotation(annotationClass) != null}
*
* @param annotationClass the Class object corresponding to the * @param annotationClass the Class object corresponding to the
* annotation type * annotation type
* @return true if an annotation for the specified annotation * @return true if an annotation for the specified annotation
...@@ -110,12 +131,15 @@ public interface AnnotatedElement { ...@@ -110,12 +131,15 @@ public interface AnnotatedElement {
<T extends Annotation> T[] getAnnotations(Class<T> annotationClass); <T extends Annotation> T[] getAnnotations(Class<T> annotationClass);
/** /**
* Returns all annotations present on this element. (Returns an array * Returns annotations that are <em>present</em> on this element.
* of length zero if this element has no annotations.) The caller of *
* this method is free to modify the returned array; it will have no * If there are no annotations <em>present</em> on this element, the return
* effect on the arrays returned to other callers. * value is an array of length 0.
* *
* @return all annotations 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.
*
* @return annotations present on this element
* @since 1.5 * @since 1.5
*/ */
Annotation[] getAnnotations(); Annotation[] getAnnotations();
...@@ -157,14 +181,16 @@ public interface AnnotatedElement { ...@@ -157,14 +181,16 @@ public interface AnnotatedElement {
<T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass); <T extends Annotation> T[] getDeclaredAnnotations(Class<T> annotationClass);
/** /**
* Returns all annotations that are directly present on this * Returns annotations that are <em>directly present</em> on this element.
* element. This method ignores inherited annotations. (Returns * This method ignores inherited annotations.
* an array of length zero if no annotations are directly present *
* on this element.) The caller of this method is free to modify * If there are no annotations <em>directly present</em> on this element,
* the returned array; it will have no effect on the arrays * the return value is an array of length 0.
* returned to other callers. *
* The caller of this method is free to modify the returned array; it will
* have no effect on the arrays returned to other callers.
* *
* @return All annotations directly present on this element * @return annotations directly present on this element
* @since 1.5 * @since 1.5
*/ */
Annotation[] getDeclaredAnnotations(); Annotation[] getDeclaredAnnotations();
......
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
package java.lang.reflect; package java.lang.reflect;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationParser;
...@@ -438,8 +437,7 @@ public abstract class Executable extends AccessibleObject ...@@ -438,8 +437,7 @@ public abstract class Executable extends AccessibleObject
*/ */
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
return annotationClass.cast(declaredAnnotations().get(annotationClass));
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
} }
/** /**
...@@ -457,7 +455,7 @@ public abstract class Executable extends AccessibleObject ...@@ -457,7 +455,7 @@ public abstract class Executable extends AccessibleObject
* {@inheritDoc} * {@inheritDoc}
*/ */
public Annotation[] getDeclaredAnnotations() { public Annotation[] getDeclaredAnnotations() {
return AnnotationSupport.unpackToArray(declaredAnnotations()); return AnnotationParser.toArray(declaredAnnotations());
} }
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
......
...@@ -1021,8 +1021,7 @@ class Field extends AccessibleObject implements Member { ...@@ -1021,8 +1021,7 @@ class Field extends AccessibleObject implements Member {
*/ */
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
return annotationClass.cast(declaredAnnotations().get(annotationClass));
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
} }
/** /**
...@@ -1040,7 +1039,7 @@ class Field extends AccessibleObject implements Member { ...@@ -1040,7 +1039,7 @@ class Field extends AccessibleObject implements Member {
* {@inheritDoc} * {@inheritDoc}
*/ */
public Annotation[] getDeclaredAnnotations() { public Annotation[] getDeclaredAnnotations() {
return AnnotationSupport.unpackToArray(declaredAnnotations()); return AnnotationParser.toArray(declaredAnnotations());
} }
private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
......
...@@ -233,8 +233,7 @@ public final class Parameter implements AnnotatedElement { ...@@ -233,8 +233,7 @@ public final class Parameter implements AnnotatedElement {
*/ */
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass); Objects.requireNonNull(annotationClass);
return annotationClass.cast(declaredAnnotations().get(annotationClass));
return AnnotationSupport.getOneAnnotation(declaredAnnotations(), annotationClass);
} }
/** /**
......
...@@ -97,9 +97,4 @@ public interface JavaLangAccess { ...@@ -97,9 +97,4 @@ public interface JavaLangAccess {
* Returns the ith StackTraceElement for the given throwable. * Returns the ith StackTraceElement for the given throwable.
*/ */
StackTraceElement getStackTraceElement(Throwable t, int i); StackTraceElement getStackTraceElement(Throwable t, int i);
/**
* Returns a directly present annotation.
*/
public <A extends Annotation> A getDirectDeclaredAnnotation(Class<?> klass, Class<A> anno);
} }
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,63 +27,29 @@ package sun.reflect.annotation; ...@@ -27,63 +27,29 @@ package sun.reflect.annotation;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import sun.reflect.Reflection;
import sun.misc.JavaLangAccess;
public final class AnnotationSupport { public final class AnnotationSupport {
private static final JavaLangAccess javaLangAccess = sun.misc.SharedSecrets.getJavaLangAccess();
/**
* Finds and returns _one_ annotation of the type indicated by
* {@code annotationClass} from the {@code Map} {@code
* annotationMap}. Looks into containers of the {@code
* annotationClass} (as specified by an the {@code
* annotationClass} type being meta-annotated with an {@code
* ContainedBy} annotation).
*
* @param annotationMap the {@code Map} used to store annotations and indexed by their type
* @param annotationClass the type of annotation to search for
*
* @return in instance of {@code annotationClass} or {@code null} if none were found
*/
public static <A extends Annotation> A getOneAnnotation(final Map<Class<? extends Annotation>, Annotation> annotationMap,
final Class<A> annotationClass) {
@SuppressWarnings("unchecked")
final A candidate = (A)annotationMap.get(annotationClass);
if (candidate != null) {
return candidate;
}
final Class<? extends Annotation> containerClass = getContainer(annotationClass);
if (containerClass != null) {
return unpackOne(annotationMap.get(containerClass), annotationClass);
}
return null; // found none
}
/** /**
* Finds and returns all annotation of the type indicated by * Finds and returns all annotation of the type indicated by
* {@code annotationClass} from the {@code Map} {@code * {@code annotationClass} from the {@code Map} {@code
* annotationMap}. Looks into containers of the {@code * annotationMap}. Looks into containers of the {@code
* annotationClass} (as specified by an the {@code * annotationClass} (as specified by an the {@code
* annotationClass} type being meta-annotated with an {@code * annotationClass} type being meta-annotated with an {@code
* ContainedBy} annotation). * Repeatable} annotation).
* *
* @param annotationMap the {@code Map} used to store annotations indexed by their type * @param annotationMap the {@code Map} used to store annotations indexed by their type
* @param annotationClass the type of annotation to search for * @param annotationClass the type of annotation to search for
* *
* @return an array of instances of {@code annotationClass} or an empty array if none were found * @return an array of instances of {@code annotationClass} or an empty array if none were found
*/ */
public static <A extends Annotation> A[] getMultipleAnnotations(final Map<Class<? extends Annotation>, Annotation> annotationMap, public static <A extends Annotation> A[] getMultipleAnnotations(
final Map<Class<? extends Annotation>, Annotation> annotationMap,
final Class<A> annotationClass) { final Class<A> annotationClass) {
final ArrayList<A> res = new ArrayList<A>(); final List<A> res = new ArrayList<A>();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
final A candidate = (A)annotationMap.get(annotationClass); final A candidate = (A)annotationMap.get(annotationClass);
...@@ -101,49 +67,10 @@ public final class AnnotationSupport { ...@@ -101,49 +67,10 @@ public final class AnnotationSupport {
return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray); return res.isEmpty() ? emptyTemplateArray : res.toArray(emptyTemplateArray);
} }
/**
* Unpacks the {@code annotationMap} parameter into an array of
* {@code Annotation}s. This method will unpack all repeating
* annotations containers (once). An annotation type is marked as a
* container by meta-annotating it the with the {@code
* ContainerFor} annotation.
*
* @param annotationMap the {@code Map} from where the annotations are unpacked
*
* @return an array of Annotation
*/
public static Annotation[] unpackToArray(Map<Class<? extends Annotation>, Annotation> annotationMap) {
List<Annotation> res = new ArrayList<>();
for (Map.Entry<Class<? extends Annotation>, Annotation> e : annotationMap.entrySet()) {
Class<? extends Annotation> annotationClass = e.getKey();
Annotation annotationInstance = e.getValue();
Class<? extends Annotation> containee = getContainee(e.getKey());
boolean isContainer = javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class) != null;
if (isContainer) {
res.addAll(unpackAll(annotationInstance, containee));
} else {
res.add(annotationInstance);
}
}
return res.isEmpty()
? AnnotationParser.getEmptyAnnotationArray()
: res.toArray(AnnotationParser.getEmptyAnnotationArray());
}
/** Helper to get the container, or null if none, of an annotation. */ /** Helper to get the container, or null if none, of an annotation. */
private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) { private static <A extends Annotation> Class<? extends Annotation> getContainer(Class<A> annotationClass) {
ContainedBy containerAnnotation = Repeatable containingAnnotation = annotationClass.getDeclaredAnnotation(Repeatable.class);
javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainedBy.class); return (containingAnnotation == null) ? null : containingAnnotation.value();
return (containerAnnotation == null) ? null : containerAnnotation.value();
}
/** Helper to get the containee, or null if this isn't a container, of a possible container annotation. */
private static <A extends Annotation> Class<? extends Annotation> getContainee(Class<A> annotationClass) {
ContainerFor containerAnnotation =
javaLangAccess.getDirectDeclaredAnnotation(annotationClass, ContainerFor.class);
return (containerAnnotation == null) ? null : containerAnnotation.value();
} }
/** Reflectively look up and get the returned array from the the /** Reflectively look up and get the returned array from the the
...@@ -156,14 +83,15 @@ public final class AnnotationSupport { ...@@ -156,14 +83,15 @@ public final class AnnotationSupport {
// value element. Get the AnnotationType, get the "value" element // value element. Get the AnnotationType, get the "value" element
// and invoke it to get the contents. // and invoke it to get the contents.
Class<?> containerClass = containerInstance.annotationType(); Class<? extends Annotation> containerClass = containerInstance.annotationType();
AnnotationType annoType = javaLangAccess.getAnnotationType(containerClass); AnnotationType annoType = AnnotationType.getInstance(containerClass);
if (annoType == null) if (annoType == null)
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations");
Method m = annoType.members().get("value"); Method m = annoType.members().get("value");
if (m == null) if (m == null)
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations"); throw new InvalidContainerAnnotationError(containerInstance +
" is an invalid container for repeating annotations");
m.setAccessible(true); m.setAccessible(true);
@SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException @SuppressWarnings("unchecked") // not provably safe, but we catch the ClassCastException
...@@ -175,53 +103,34 @@ public final class AnnotationSupport { ...@@ -175,53 +103,34 @@ public final class AnnotationSupport {
IllegalArgumentException | // parameters doesn't match IllegalArgumentException | // parameters doesn't match
InvocationTargetException | // the value method threw an exception InvocationTargetException | // the value method threw an exception
ClassCastException e) { // well, a cast failed ... ClassCastException e) { // well, a cast failed ...
throw new InvalidContainerAnnotationError(containerInstance + " is an invalid container for repeating annotations", throw new InvalidContainerAnnotationError(
containerInstance + " is an invalid container for repeating annotations",
e, e,
containerInstance, containerInstance,
null); null);
} }
} }
/* Sanity check type of and return the first annotation instance
* of type {@code annotationClass} from {@code
* containerInstance}.
*/
private static <A extends Annotation> A unpackOne(Annotation containerInstance, Class<A> annotationClass) {
if (containerInstance == null) {
return null;
}
try {
return annotationClass.cast(getValueArray(containerInstance)[0]);
} catch (ArrayIndexOutOfBoundsException | // empty array
ClassCastException | // well, a cast failed ...
NullPointerException e) { // can this NP? for good meassure
throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s",
containerInstance, annotationClass),
e,
containerInstance,
annotationClass);
}
}
/* Sanity check type of and return a list of all the annotation /* Sanity check type of and return a list of all the annotation
* instances of type {@code annotationClass} from {@code * instances of type {@code annotationClass} from {@code
* containerInstance}. * containerInstance}.
*/ */
private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance, Class<A> annotationClass) { private static <A extends Annotation> List<A> unpackAll(Annotation containerInstance,
Class<A> annotationClass) {
if (containerInstance == null) { if (containerInstance == null) {
return Collections.emptyList(); // container not present return Collections.emptyList(); // container not present
} }
try { try {
A[] a = getValueArray(containerInstance); A[] a = getValueArray(containerInstance);
ArrayList<A> l = new ArrayList<>(a.length); List<A> l = new ArrayList<>(a.length);
for (int i = 0; i < a.length; i++) for (int i = 0; i < a.length; i++)
l.add(annotationClass.cast(a[i])); l.add(annotationClass.cast(a[i]));
return l; return l;
} catch (ClassCastException | } catch (ClassCastException |
NullPointerException e) { NullPointerException e) {
throw new InvalidContainerAnnotationError(String.format("%s is an invalid container for repeating annotations of type: %s", throw new InvalidContainerAnnotationError(
String.format("%s is an invalid container for repeating annotations of type: %s",
containerInstance, annotationClass), containerInstance, annotationClass),
e, e,
containerInstance, containerInstance,
......
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 7154390 * @bug 7154390 8005712
* @summary Unit test for repeated annotation reflection * @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 * @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
...@@ -58,7 +58,7 @@ public class RepeatedUnitTest { ...@@ -58,7 +58,7 @@ public class RepeatedUnitTest {
checkMultiplier(Me1.class.getField("foo"), 1); checkMultiplier(Me1.class.getField("foo"), 1);
// METHOD // METHOD
checkMultiplier(Me1.class.getDeclaredMethod("mee", null), 100); checkMultiplier(Me1.class.getDeclaredMethod("mee", (Class<?>[])null), 100);
// INNER CLASS // INNER CLASS
checkMultiplier(Me1.MiniMee.class, 1000); checkMultiplier(Me1.MiniMee.class, 1000);
...@@ -84,8 +84,7 @@ public class RepeatedUnitTest { ...@@ -84,8 +84,7 @@ public class RepeatedUnitTest {
static void packageRepeated(AnnotatedElement e) { static void packageRepeated(AnnotatedElement e) {
Containee c = e.getAnnotation(Containee.class); Containee c = e.getAnnotation(Containee.class);
check(c.value() == 1); check(c == null);
check(2 == countAnnotation(e, Containee.class)); check(2 == countAnnotation(e, Containee.class));
c = e.getAnnotations(Containee.class)[0]; c = e.getAnnotations(Containee.class)[0];
...@@ -93,7 +92,7 @@ public class RepeatedUnitTest { ...@@ -93,7 +92,7 @@ public class RepeatedUnitTest {
c = e.getAnnotations(Containee.class)[1]; c = e.getAnnotations(Containee.class)[1];
check(c.value() == 2); check(c.value() == 2);
check(2 == containsAnnotationOfType(e.getAnnotations(), Containee.class)); check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
} }
static void packageContainer(AnnotatedElement e) { static void packageContainer(AnnotatedElement e) {
...@@ -161,14 +160,26 @@ public class RepeatedUnitTest { ...@@ -161,14 +160,26 @@ public class RepeatedUnitTest {
} }
static void checkMultiplier(AnnotatedElement e, int m) { static void checkMultiplier(AnnotatedElement e, int m) {
// Basic sanity of non-repeating getAnnotation(Class)
check(e.getAnnotation(NonRepeated.class).value() == 5 * m); check(e.getAnnotation(NonRepeated.class).value() == 5 * m);
// Check count of annotations returned from getAnnotations(Class)
check(4 == countAnnotation(e, Containee.class)); check(4 == countAnnotation(e, Containee.class));
check(1 == countAnnotation(e, Container.class)); check(1 == countAnnotation(e, Container.class));
check(1 == countAnnotation(e, NonRepeated.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(Containee.class)[2].value() == 3 * m);
check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m); check(e.getAnnotations(NonRepeated.class)[0].value() == 5 * m);
// Check getAnnotation(Class)
check(e.getAnnotation(Containee.class) == null);
check(e.getAnnotation(Container.class) != null);
// Check count of annotations returned from getAnnotations()
check(0 == containsAnnotationOfType(e.getAnnotations(), Containee.class));
check(1 == containsAnnotationOfType(e.getAnnotations(), Container.class));
check(1 == containsAnnotationOfType(e.getAnnotations(), NonRepeated.class));
} }
static void check(Boolean b) { static void check(Boolean b) {
......
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,7 +26,6 @@ package subpackage; ...@@ -26,7 +26,6 @@ package subpackage;
import java.lang.annotation.*; import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ContainedBy(Container.class)
@Repeatable(Container.class) @Repeatable(Container.class)
public @interface Containee { public @interface Containee {
int value(); int value();
......
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,7 +26,6 @@ package subpackage; ...@@ -26,7 +26,6 @@ package subpackage;
import java.lang.annotation.*; import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ContainerFor(Containee.class)
public @interface Container { public @interface Container {
Containee[] value(); Containee[] value();
} }
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,7 +27,6 @@ import java.lang.annotation.*; ...@@ -27,7 +27,6 @@ import java.lang.annotation.*;
@Inherited @Inherited
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ContainedBy(InheritedContainer.class)
@Repeatable(InheritedContainer.class) @Repeatable(InheritedContainer.class)
public @interface InheritedContainee { public @interface InheritedContainee {
int value(); int value();
......
/* /*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,7 +27,6 @@ import java.lang.annotation.*; ...@@ -27,7 +27,6 @@ import java.lang.annotation.*;
@Inherited @Inherited
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@ContainerFor(InheritedContainee.class)
public @interface InheritedContainer { public @interface InheritedContainer {
InheritedContainee[] value(); InheritedContainee[] value();
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册