Hi Joe,
I propose some "premature" optimization for
AnnotatedElement.getDeclaredAnnotationsByType(). This implementation
calls either getDeclaredAnnotatios() once or
getDeclaredAnnotation(Class) once, depending on whether the
annotation type is repeatable or not respectively (this check also
requires a getDeclaredAnnotation() call, but I propose to extend
AnnotationType in the future to provide with cached containerClass
directly). Also, it is about 7x faster to use
annotationClass.isInstance(ann) to check for the type of annotation
instead of ann.annotationType() == annotationClass which goes through
annotation Proxy, etc...
Here it is:
default <T extends Annotation> T[]
getDeclaredAnnotationsByType(Class<T> annotationClass) {
Objects.requireNonNull(annotationClass);
Repeatable repeatable =
annotationClass.getDeclaredAnnotation(Repeatable.class);
// non-repeatable: just delegate to getDeclaredAnnotation and
return wrapped result
if (repeatable == null) {
T ann = getDeclaredAnnotation(annotationClass);
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(annotationClass, ann
== null ? 0 : 1);
if (ann != null) result[0] = ann;
return result;
}
// repeatable: iterate all declared annotations, find
directly and indirectly present
// and also determine the order (directlyPresentFirst)...
Class<? extends Annotation> containerClass = repeatable.value();
T directlyPresent = null;
T[] indirectlyPresent = null;
boolean directlyPresentFirst = false;
for (Annotation ann : getDeclaredAnnotations()) {
if (directlyPresent == null &&
annotationClass.isInstance(ann)) {
directlyPresent = annotationClass.cast(ann);
if (indirectlyPresent != null) {
break;
}
} else if (indirectlyPresent == null &&
containerClass.isInstance(ann)) {
indirectlyPresent = AnnotationSupport.getValueArray(ann);
if (directlyPresent != null) {
directlyPresentFirst = true;
break;
}
}
}
// concatenate directlyPresent and indirectlyPresent annotations
@SuppressWarnings("unchecked")
T[] result = (directlyPresent == null && indirectlyPresent !=
null)
? indirectlyPresent
: (T[]) Array.newInstance(annotationClass,
(directlyPresent == null ? 0 : 1) +
(indirectlyPresent == null ? 0 :
indirectlyPresent.length));
if (directlyPresent != null) {
if (indirectlyPresent == null || indirectlyPresent.length
== 0) {
result[0] = directlyPresent;
} else {
result[directlyPresentFirst ? 0 :
indirectlyPresent.length] = directlyPresent;
System.arraycopy(indirectlyPresent, 0, result,
directlyPresentFirst ? 1 : 0,
indirectlyPresent.length);
}
}
return result;
}
Regards, Peter
On 10/25/2013 10:40 AM, Joe Darcy wrote:
Hi Joel and Peter,
On 10/24/2013 07:10 AM, Peter Levart wrote:
Hi Joe,
I see two problems with the implementation in
*AnnotatedElementSupport*. The first is the treatment of
declared-only annotations where the code returns either directly
present or in-directly present repeatable annotations, but not
both. So in the following example:
@Ann(1)
@AnnCont({@Ann(2), @Ann(3)})
it will only return [@Ann(1)], but I think it should return all of
them [@Ann(1), @Ann(2), @Ann(3)] - does the spec. define that?
[snip]
From your feedback (and a closer reading of the specifciation), I've
reworked the specifications and implemenations of the default
methods for get[Declared]AnnotationsByType:
http://cr.openjdk.java.net/~darcy/8005294.2/
Tests still need to be written, but this implementation should be
much closed to what is needed.
Thanks,
-Joe