FULL PRODUCT VERSION :
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
MacOS X 10.9.4
(uname reports: Darwin Kernel Version 13.3.0)
A DESCRIPTION OF THE PROBLEM :
I have not yet tried all of the AnnotatedType-related API, but the first one I reached for, Class.getAnnotatedSuperclass(), does not work.
It returns AnnotatedType implementations that do not actual return any of the annotations present in the type. Reading the class file shows the type annotations are correctly stored by javac. But they are not accessible via the new reflection API whose sole purpose is to access them.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the program in the "Source code" section below. It contains a class whose "extends" clause uses type annotations, both on the superclass and on the type variables (the superclass is a generic type).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would expect output from the program to include information about the type annotations:
----
TypeAnnotationBug.TypeAnnotationBug$X<P1, P2, java.lang.Class<P1>> =>
@TypeAnnotationBug$A()
Type Variable P1 =>
@TypeAnnotationBug$B()
Type Variable P2 =>
@TypeAnnotationBug$C()
Type Variable java.lang.Class<P1> =>
@TypeAnnotationBug$D()
Type Variable P1 =>
@TypeAnnotationBug$E()
ACTUAL -
No annotation information seems to be available via clazz.getAnnotatedSuperclass().getAnnotations() nor on the actual type arguments from clazz.getAnnotatedSuperclass().getAnnotatedActualTypeArguments().
Here is the output I get from the sample program:
----
TypeAnnotationBug.TypeAnnotationBug$X<P1, P2, java.lang.Class<P1>> =>
Type Variable P1 =>
Type Variable P2 =>
Type Variable java.lang.Class<P1> =>
Type Variable P1 =>
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class TypeAnnotationBug {
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface A {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface B {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface C {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface D {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface E {
}
static class X<P1, P2, P3> {
}
static class Y<P1, P2> extends @A X<@B P1, @C P2, @D Class<@E P1>> {
}
public static void main(String args[]) {
AnnotatedType x = Y.class.getAnnotatedSuperclass();
System.out.println(x.getType().getTypeName() + " => ");
for (Annotation a : x.getAnnotations()) {
System.out.println(a);
}
AnnotatedParameterizedType xpt = (AnnotatedParameterizedType) x;
int i = 0;
for (AnnotatedType arg : xpt.getAnnotatedActualTypeArguments()) {
Type argType = ((ParameterizedType) xpt.getType()).getActualTypeArguments()[i++];
System.out.println("Type Variable " + argType.getTypeName() + " => ");
for (Annotation a : arg.getAnnotations()) {
System.out.println(a);
}
if (arg instanceof AnnotatedParameterizedType) {
int j = 0;
for (AnnotatedType nestedArg : ((AnnotatedParameterizedType) arg).getAnnotatedActualTypeArguments()) {
Type nestedArgType = ((ParameterizedType) arg.getType()).getActualTypeArguments()[j++];
System.out.println(" Type Variable " + nestedArgType.getTypeName() + " => ");
for (Annotation a : nestedArg.getAnnotations()) {
System.out.println(a);
}
}
}
}
}
}
---------- END SOURCE ----------
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
MacOS X 10.9.4
(uname reports: Darwin Kernel Version 13.3.0)
A DESCRIPTION OF THE PROBLEM :
I have not yet tried all of the AnnotatedType-related API, but the first one I reached for, Class.getAnnotatedSuperclass(), does not work.
It returns AnnotatedType implementations that do not actual return any of the annotations present in the type. Reading the class file shows the type annotations are correctly stored by javac. But they are not accessible via the new reflection API whose sole purpose is to access them.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the program in the "Source code" section below. It contains a class whose "extends" clause uses type annotations, both on the superclass and on the type variables (the superclass is a generic type).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would expect output from the program to include information about the type annotations:
----
TypeAnnotationBug.TypeAnnotationBug$X<P1, P2, java.lang.Class<P1>> =>
@TypeAnnotationBug$A()
Type Variable P1 =>
@TypeAnnotationBug$B()
Type Variable P2 =>
@TypeAnnotationBug$C()
Type Variable java.lang.Class<P1> =>
@TypeAnnotationBug$D()
Type Variable P1 =>
@TypeAnnotationBug$E()
ACTUAL -
No annotation information seems to be available via clazz.getAnnotatedSuperclass().getAnnotations() nor on the actual type arguments from clazz.getAnnotatedSuperclass().getAnnotatedActualTypeArguments().
Here is the output I get from the sample program:
----
TypeAnnotationBug.TypeAnnotationBug$X<P1, P2, java.lang.Class<P1>> =>
Type Variable P1 =>
Type Variable P2 =>
Type Variable java.lang.Class<P1> =>
Type Variable P1 =>
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.AnnotatedParameterizedType;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class TypeAnnotationBug {
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface A {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface B {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface C {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface D {
}
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
@interface E {
}
static class X<P1, P2, P3> {
}
static class Y<P1, P2> extends @A X<@B P1, @C P2, @D Class<@E P1>> {
}
public static void main(String args[]) {
AnnotatedType x = Y.class.getAnnotatedSuperclass();
System.out.println(x.getType().getTypeName() + " => ");
for (Annotation a : x.getAnnotations()) {
System.out.println(a);
}
AnnotatedParameterizedType xpt = (AnnotatedParameterizedType) x;
int i = 0;
for (AnnotatedType arg : xpt.getAnnotatedActualTypeArguments()) {
Type argType = ((ParameterizedType) xpt.getType()).getActualTypeArguments()[i++];
System.out.println("Type Variable " + argType.getTypeName() + " => ");
for (Annotation a : arg.getAnnotations()) {
System.out.println(a);
}
if (arg instanceof AnnotatedParameterizedType) {
int j = 0;
for (AnnotatedType nestedArg : ((AnnotatedParameterizedType) arg).getAnnotatedActualTypeArguments()) {
Type nestedArgType = ((ParameterizedType) arg.getType()).getActualTypeArguments()[j++];
System.out.println(" Type Variable " + nestedArgType.getTypeName() + " => ");
for (Annotation a : nestedArg.getAnnotations()) {
System.out.println(a);
}
}
}
}
}
}
---------- END SOURCE ----------
- duplicates
-
JDK-8148504 javac omits target_path for some type annotations in class extends/implements position
-
- Closed
-