FULL PRODUCT VERSION :
java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
15.6.0 Darwin Kernel Version 15.6.0: Mon Aug 29 20:21:34 PDT 2016; root:xnu-3248.60.11~1/RELEASE_X86_64 x86_64
A DESCRIPTION OF THE PROBLEM :
1. A subclass implements a method with the same signature as a method in the super class, except that the bounds of a type parameter are reordered.
2. The subclass method has an @Override annotation.
3. javac compiles this code without any errors or warnings.
4. When you call the method on a variable whose declared type is the superclass but run-time type is the subclass, the java runtime will dispatch to the superclass method, instead of the subclass method as implied by the @Override notation.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile my code below and run it. I did this with:
javac ReorderedBounds.java ; java -cp . ReorderedBounds
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I was expecting to see the following output:
OrderedChild
ReorderedChild
ACTUAL -
Instead I saw this output:
OrderedChild
Parent
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
import java.io.Serializable;
/** An example where the compiler allows @Override but doesn't actually override the method. */
public class ReorderedBounds {
public static class Parent {
public <T extends Appendable & Serializable> void printClassName(T t) {
System.out.println("Parent");
}
}
public static class OrderedChild extends Parent {
@Override
public <T extends Appendable & Serializable> void printClassName(T t) {
System.out.println("OrderedChild");
}
}
public static class ReorderedChild extends Parent {
@Override
public <T extends Serializable & Appendable> void printClassName(T t) {
System.out.println("ReorderedChild");
}
}
public static void main(String[] args) {
Parent p = new OrderedChild();
// We will get "OrderedChild" as expected.
p.printClassName(new StringBuilder());
p = new ReorderedChild();
// We expect virtual dispatch to print "ReorderedChild", but instead we get "Parent".
p.printClassName(new StringBuilder());
}
}
---------- END SOURCE ----------