Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8284566

javac does not report clashing default methods

XMLWordPrintable

    • generic
    • generic

      A DESCRIPTION OF THE PROBLEM :
      Relates to JDK-8030143

      This is probably a bug both with the JLS and javac. JLS 18 §8.4.8.4. "Inheriting Methods with Override-Equivalent Signatures" says:
      > It is a compile-time error if a class C inherits a default method whose signature is override-equivalent with another method inherited by C

      The issue here is probably that it says "override-equivalent", while it should probably consider "subsignatures" instead.
      Though due to how "inherits" is defined by §8.4.8. "Inheritance, Overriding, and Hiding", the `static` method clash shown below is probably not covered by the above statement, but instead by §8.4.8.2. "Hiding (by Class Methods)".

      This leads to cases where javac permits conflicting interface default methods with same erased signature (subsignature) resulting in malformed classes.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      javac should refuse to compile both test classes.
      ACTUAL -
      For Test1 the code compiles without any errors or warnings, but the call to `m(List<Integer>)` in reality calls `m(List<String>)` which leads to a ClassCastException in the method body.

      For Test2 the code compiles without any errors or warnings, but the call to `m(List<Integer>)` leads to an IncompatibleClassChangeError.


      ---------- BEGIN SOURCE ----------
      ### TEST 1 ###
      import java.util.List;

      interface Test1 {
          class C {
              public void m(List<String> l) {
                  System.out.println("class");
                  String s = l.get(0);
              }
          }

          interface I {
              default void m(List<Integer> l) {
                  System.out.println("interface");
                  Integer i = l.get(0);
              }
          }

          class T extends C implements I {}

          public static void main(String... args) {
              new T().m(List.of("a"));
              // Fails with ClassCastException
              new T().m(List.of(1));
          }
      }

      ### TEST 2 ###
      import java.util.List;

      interface Test2 {
          class C {
              public static void m(List<String> l) {
                  System.out.println("class");
                  String s = l.get(0);
              }
          }

          interface I {
              default void m(List<Integer> l) {
                  System.out.println("interface");
                  Integer i = l.get(0);
              }
          }

          class T extends C implements I {}

          public static void main(String... args) {
              // Fails with IncompatibleClassChangeError
              new T().m(List.of(1));
          }
      }

      ---------- END SOURCE ----------

        1. Test1.java
          0.6 kB
        2. Test2.java
          0.5 kB

            vromero Vicente Arturo Romero Zaldivar
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: