Proposal to make new-in-Java-SE-8 methods on AnnotatedElement default methods
Joe Darcy
joe.darcy at oracle.com
Thu Oct 24 19:08:05 PDT 2013
Hi Joel,
Reponding to point question below...
On 10/24/2013 08:34 AM, Joel Borggrén-Franck wrote:
> Hi Joe,
>
> I agree this would be nice to do, but see comments inline,
>
> On 24 okt 2013, at 15:16, Joe Darcy <joe.darcy at oracle.com> wrote:
>>
>> + * @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
>> @@ -230,8 +241,10 @@
>> * @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) {
>>
> This is the wrong order. The precise lookup of an associated annotation is declared then inherited, quoting the javadoc for AnnotatedElement:
>
> "• An annotation A is associated with an element E if either:
> • A is directly or indirectly present on E; or
> • No annotation of A 's type is directly or indirectly present on E, and E is a class, and A's type is inheritable, and A is associated with the superclass of E."
>
>> + * @implSpec The default implementation first calls {@link
>> + * #getDeclaredAnnotation(Class)} on the argument type. If the
>> + * annotation is directly 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 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 directly or indirectly present
>> * @param annotationClass the Class object corresponding to the
>> @@ -277,7 +315,9 @@
>> * @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) {
>>
> This should work.
>
>> + * @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
>> @@ -247,7 +265,18 @@
>> * @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) {
>>
> Wouldn't this risk the same issues as when we turned isAnnotationPresent() into a default?
>
>
No; we don't have the same hazard here as with isAnnotationPresent. The
issue we ran into with making isAnnotationPresent a default method was
that isAnnotationPresent was part of the original AnnotatedElement
interface defined way back in Java SE 5. In implementation decision in
javac did not expose the existence of default methods to code being
compiled under source levels less than 8. That is a pragmatic choice and
usually gives the desired result, but not in this case.
Making the new-in-Java-SE-8 methods in AnnotatedElement defaults follows
the generally recommended way to evolve interfaces when new methods are
added to them.
Thanks for the comments; I'll get to work fixing the implementation,
-Joe
More information about the enhanced-metadata-spec-discuss
mailing list