Community
Participate
Working Groups
Using 3.2M1 candidate, the following code doesn't compile. p/Ann.java ---------- package p; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.ElementType.CONSTRUCTOR; @Target(CONSTRUCTOR) @Retention(RUNTIME) public @interface Ann { String message(); } -------------------------------------------------------------- p/X.java -------- package p; import java.lang.reflect.Constructor; public class X { public static void main(String[] args) { final Class<Ann> AnnClass = Ann.class; Constructor[] constrs = X.class.getConstructors(); for (Constructor constructor : constrs) { final String message = constructor.getAnnotation(AnnClass).message(); System.out.println(message); } } } The compiler infers Annotation as the type for constructor.getAnnotation(AnnClass) instead of Ann. Then message() is reported as undefined for the type Annotation. The signature of Constructor.getAnnotation(...) is: public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { ... } So I would expect p.Ann as the return type.
javac compiles that code. But if you replace: final Class<Ann> AnnClass = Ann.class; with: final Class AnnClass = Ann.class; then javac reports the same error as we do.
Interestingly, we accept the following: public class X { public static void main(String[] args) { try { X.class.getConstructor(new Class[0]).getAnnotation(Ann.class).message(); } catch(Exception e) { } } } @interface Ann { String message(); }
Weird. Javac accepts the following code: import java.lang.reflect.Constructor; public class X { void bar(Constructor constructor, Class<Ann> ann) { constructor.getAnnotation(ann).message(); // OK } } @interface Ann { String message(); } but rejects: public class X { void bar(Constructor constructor, Class<Ann> ann) { constructor.getAnnotation(ann).message(); // KO - cannot find method #message() for Annotation } } class Constructor<V> { <T extends Annotation> T getAnnotation(Class<T> c) { return null; } } class Annotation {} class Ann extends Annotation { void message() {} } I am a bit puzzled by this difference in behavior, and am wondering if Annotation#getAnnotation(...) is meant to be treated in a special way (which no longer occurs in second example when defining source types) in a similar fashion as Object#getClass(...). Couldn't find any mention of this in the spec though.
Suspicion is that this is a bug in javac, and the code should be rejected. Added GenericTypeTest#test800-802.
Closing as javac bug.
*** Bug 163560 has been marked as a duplicate of this bug. ***
Javac bug is http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6400189