JDK 8 RFR, redux, for JDK-8005294 : Consider default methods for additions to AnnotatedElement
Peter Levart
peter.levart at gmail.com
Wed Oct 30 07:52:21 UTC 2013
On 10/30/2013 02:57 AM, Joe Darcy wrote:
> On 10/29/2013 06:37 PM, Joe Darcy wrote:
>> Hi Joel,
>>
>> On 10/29/2013 09:20 AM, Joel Borggrén-Franck wrote:
>>> Hi Joe, Peter,
>>>
>>> On 29 okt 2013, at 07:09, Joe Darcy <joe.darcy at oracle.com> wrote:
>>>> Your comments, along with some spec refinements from the other
>>>> OpenJDK list, are reflected in the next iteration of the webrev:
>>>>
>>>> http://cr.openjdk.java.net/~darcy/8005294.5/
>>>>
>>>> Thanks,
>>>>
>>> 259 if (result.length == 0 && // Neither directly nor
>>> indirectly present
>>> 260 this instanceof Class && // the element is a class
>>> 261 AnnotationType.getInstance(annotationClass).isInherited()) {
>>> // Inheritable
>>> 262 ...
>>>
>>> j.l.Class is final and has an implementation of getAnnotationsByType
>>> so everything in this branch is dead code. I understand you might
>>> want to document how the lookup is supposed to happen if you have
>>> inheritance semantics for your AnnotatedElement but IMHO this isn't
>>> the way to do it. Just delegate to getDeclaredAnnotationsByType.
>>
>> Summarizing an off-list discussion, in terms of making this
>> particular method robust in the face of of possible alternative
>> versions of java.lang.Class and friends, I think it is acceptable to
>> introduce what will in practice be dead code with the version of
>> java.lang.Class in JDK 8.
>>
>>>
>>> 291 * @since 1.8
>>> 292 */
>>>
>>> 293 default <T extends Annotation> T
>>> getDeclaredAnnotation(Class<T> annotationClass) {
>>>
>>> I keep forgetting that this one is new to 8. My reservations about
>>> making this a default was based on (the misconception) that this was
>>> a 5 method. This method looks good.
>>>
>>> For getDeclaredAnnotationsByType() the idea of having two
>>> implementations of the same logic, one taking arrays as arguments
>>> and the other Maps, seems wrong. I would strongly prefer if we only
>>> had one implementation, calling into AnnotationSupport from this
>>> method. Something like
>>>
>>> default <T extends Annotation> T[]
>>> getDeclaredAnnotationsByType(Class<T> annotationClass) {
>>> Objects.requireNonNull(annotationClass);
>>> return
>>> AnnotationSupport.getDirectlyAndIndirectlyPresent(Arrays.stream(getDeclaredAnnotations()).collect(Collectors.toMap(
>>> (a -> a.getClass()),
>>> Function.identity())),
>>> annotationClass);
>>> }
>>>
>>> I can't see these default methods as the code we should be spending
>>> time optimizing.
>>
>> Given the improved maintenance situation and the low expecte duty
>> cycle of the default method implementations, despite having worked on
>> what should be a fast-ish getDeclaredAnnotation implementation, I'm
>> willing to replace it by a call to AnnotationSupport wrapped around a
>> call to getDeclaredAnnotations().
>>
>> This style of implementation is allowed by the current @implSpec for
>> the method.
>>
>> However, I'm not sure the
>> AnnotationSupport.getDirectlyAndIndirectlyPresent call can work as
>> currently formulated will work since I believe what needs to be
>> called is "a.getAnnotationType()" rather than "a.getClass()", but
>> unfortunately "getAnnotationType()" is not defined on
>> AnnotatedElement so reflection would be needed to call
>> getAnnotationType :-(
>>
>
> I retract my previous comments; I was confusing "annotationType" and
> "value()" in terms of where they are defined. This version of
> getDeclaredAnnotationsByType passes the battery of regression tests:
>
> default <T extends Annotation> T[]
> getDeclaredAnnotationsByType(Class<T> annotationClass) {
> Objects.requireNonNull(annotationClass);
> return AnnotationSupport.
> getDirectlyAndIndirectlyPresent(Arrays.stream(getDeclaredAnnotations()).
> collect(Collectors.toMap(
> (a -> a.annotationType()),
> Function.identity(),
> ((first,second) -> first),
> () -> new LinkedHashMap<>() )),
> annotationClass);
> }
Hi Joe,
I suggest using method references where possible, which saves from
generating two (of three) synthetic methods in AnnotatedElement interface:
Collectors.toMap(
Annotation::annotationType,
Function.identity(),
(first, second) -> first,
LinkedHashMap::new)
Regards, Peter
>
> I've prepared a new version of the webrev with this change as well as
> a slightly-refactored regression test:
>
> http://cr.openjdk.java.net/~darcy/8005294.6
>
> Thanks,
>
> -Joe
>
More information about the core-libs-dev
mailing list