repeating annotations comments
michael keith
michael.keith at oracle.com
Fri Dec 14 13:59:03 PST 2012
Here are some observations from looking at the current state of the
repeating annotation spec. If I got something wrong, here, I trust
you'll let me know :-)
1. The getAnnotation(Class<T>) method is being changed to look through
container annotations. This method returns an Annotation, i.e. a single
instance, so applying it to repeated ones is necessarily going to have
to return only one. But having it look through container annotation ends
up not being very productive, and may be causing it to be
counter-productive.
Look-through for this method is not productive because the call is being
made precisely in the legacy cases when only one annotation was
expected, but a container annotation will only be synthesized when
multiples are present. So look-through does not really help get "the"
expected annotation. The only case when it would be useful is in the
unlikely case when the container annotation is used explicitly and
contains a single contained annotation.
It may be counter-productive for three reasons.
The first is because getting a random single annotation in the presence
of multiples is potentially dangerous since the calling code will
continue without knowing that multiples are present, so legacy code is
essentially broken, but will not actually fail. It will just be
semantically incorrect.
The second is because I didn't see (and I may just have missed it) where
it was defined that if both T and TC were present that T would be
guaranteed to be returned and not some instance within TC. Example 1.2-3
shows this to be the case but I didn't see that it was specified
behavior rather than just because the T occurred before the TC. If the
example had been TC and then T would the instance of T be returned? This
could be important because existing code to handle this case checks for
the container annotation TC and then checks for the single annotation T.
However, if checking for T happens to look through TC and return one of
the contained annotations in TC instead of the lone T annotation then
the lone annotation would not get found.
The third is because all of the code that is currently out there that
needs to check for the previous case, i.e. both T and TC occurring, will
get a false positive in the simpler case of multiple instances of T
annotations (as per the second part of example 1.2-1 in the doc). The
getAnnotation(TC) will return the synthesized TC containing all of the
instances of T, and then getAnnotation(T) will return one of those same
instances again. Legacy code will assume that the result of
getAnnotation(T) is disjoint from the contained annotations of the TC
returned by getAnnotation(TC).
Note: The same argument applies to the isAnnotationPresent(T) method
since it is defined in terms of getAnnotation(T).
2. Given that get[Declared]Annotations() is going to change and return
multiple instances of the same annotation (rather than a single instance
of a container annotation) existing implementations are going to have to
be fixed since there is no backwards compatibility there at all.
3. In general, it appears that once an annotation is made repeatable the
annotation processing code is inevitably going to have to change in
order to handle the repeatability. We were willing to take that hit,
particularly since the new behavior requires opting in, and that means
that specs could do so at their own discretion. However, the code to
handle both the new and the old (i.e. be able to process both new
repeatable annotations as well as the older idiomatic container
annotations) is a little less intuitive to write than I had hoped it
would be. The easiest way might just be to create a Set of instances to
avoid duplicates. Not rocket science, just not what I would have expected.
Thanks,
-Mike
More information about the enhanced-metadata-spec-discuss
mailing list