JDK-8166363 : Method with reordered type parameter bounds compiles with @Override annotation but does not actually override superclass method.
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8,9
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2016-09-20
  • Updated: 2016-10-07
  • Resolved: 2016-09-28
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b139Fixed
Related Reports
Duplicate :  
Description
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 ----------


Comments
A fix is available and is under review.
21-09-2016

Eclipse compiles & runs this program fine. Javac fails to emit a bridge.
21-09-2016

Below is the result == 8uxx - Fail (including 8u112 ea b-06) 9 ea b-135 - Fail ==
20-09-2016

It does look like issue, Calling a method declared type is the superclass but run-time type is the subclas, the java runtime will dispatch to the superclass method, instead of the subclass method as implied by the @Override notation. Expected == OrderedChild ReorderedChild Actual==8u102== -sh-4.1$ /opt/java/jdk1.8.0_102/bin/javac ReorderedBounds.java -sh-4.1$ /opt/java/jdk1.8.0_102/bin/java ReorderedBounds OrderedChild Parent ==9 ea b-135== -sh-4.1$ /opt/java/jdk-9_ea-135/bin/javac ReorderedBounds.java A-sh-4.1$ /opt/java/jdk-9_ea-135/bin/java ReorderedBounds OrderedChild Parent
20-09-2016