Duplicate :
|
FULL PRODUCT VERSION : java version "1.8.0_45" Java(TM) SE Runtime Environment (build 1.8.0_45-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows [Version 6.1.7601] A DESCRIPTION OF THE PROBLEM : @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExampleAnnotation {} public abstract class AbstractExample<T extends BeanInterface> { public abstract void exampleMethod(T bean); } public class ImplementationExample extends AbstractExample<BeanImplementation>{ @Override @ExampleAnnotation public void exampleMethod(BeanImplementation bean) { } } Where BeanImplementation is an implementation of BeanInterface. If I compile the code using Java 8u45 and I list which methods of the ImplementationExample class have the annotation ExampleAnnotation using the following piece of code: Class<ImplementationExample> cls = ImplementationExample.class; List<Method> methods = new ArrayList<Method>(); methods.addAll(Arrays.asList(cls.getDeclaredMethods())); for (Method method : methods) { System.out.println("method: " + method.getName() + " annotation: " + method.getAnnotation(ExampleAnnotation.class)); } Then I get that both these methods: ImplementationExample.exampleMethod(BeanImplementation) ImplementationExample.exampleMethod(BeanInterface) If I use Java 7 or the Java 8 Eclipse Compiler then only the first method is annotated and this should be the correct behavior. Is this a bug in the java 8 compiler? Or am I doing something wrong? I would expect the behavior to be the same as in Java 7. REGRESSION. Last worked in version 7u75 ADDITIONAL REGRESSION INFORMATION: java version "1.7.0_72" Java(TM) SE Runtime Environment (build 1.7.0_72-b14) Java HotSpot(TM) 64-Bit Server VM (build 24.72-b04, mixed mode) STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : HERE THE CODE NEEDED //Test Method Annotation @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExampleAnnotation {} //Abstract class with method whose input is parameterized like this: public abstract class AbstractExample<T extends BeanInterface> { public abstract void exampleMethod(T bean); } //Implementation of the abstract class public class ImplementationExample extends AbstractExample<BeanImplementation>{ @Override @ExampleAnnotation public void exampleMethod(BeanImplementation bean) { } } //Where BeanImplementation is an implementation of the interface BeanInterface. If I compile the code using Java 8u45 and I list which methods of the ImplementationExample class have the annotation ExampleAnnotation using the following piece of code: Class<ImplementationExample> cls = ImplementationExample.class; List<Method> methods = new ArrayList<Method>(); methods.addAll(Arrays.asList(cls.getDeclaredMethods())); for (Method method : methods) { System.out.println("method: " + method.getName() + " annotation: " + method.getAnnotation(ExampleAnnotation.class)); } Then I get that both these methods: ImplementationExample.exampleMethod(BeanImplementation) ImplementationExample.exampleMethod(BeanInterface) If I use Java 7 or the Java 8 Eclipse Compiler then only the first method is annotated. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - Only the following method should be detected to have the annotation ExampleAnnotation: ImplementationExample.exampleMethod(BeanImplementation) ACTUAL - Both these two methods have been detected to have the annotation ExampleAnnotation: ImplementationExample.exampleMethod(BeanImplementation) ImplementationExample.exampleMethod(BeanInterface) ERROR MESSAGES/STACK TRACES THAT OCCUR : No error message REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- //ExampleAnnotation.java import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ExampleAnnotation {} //BeanInterface.java public interface BeanInterface {} //BeanImplementation.java public class BeanImplementation implements BeanInterface {} //AbstractExample.java public abstract class AbstractExample<T extends BeanInterface> { public abstract void exampleMethod(T bean); } //ImplementationExample.java public class ImplementationExample extends AbstractExample<BeanImplementation>{ @Override @ExampleAnnotation public void exampleMethod(BeanImplementation bean) {} } //TestAnnotation .java import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class TestAnnotation { public static void main(String[] args) { listAllMethods(); } private static void listAllMethods() { Class<ImplementationExample> cls = ImplementationExample.class; List<Method> methods = new ArrayList<Method>(); methods.addAll(Arrays.asList(cls.getDeclaredMethods())); for (Method method : methods) { System.out.println("method: " + method.getName() + " annotation: " + method.getAnnotation(ExampleAnnotation.class)); System.out.println(method); } } } ---------- END SOURCE ---------- SUPPORT : YES