8306854: javac with '-source 7' should honor default methods in implemented Java 8 interfaces
Alex Buckley
alex.buckley at oracle.com
Tue Apr 25 17:09:41 UTC 2023
On 4/25/2023 8:33 AM, Volker Simonis wrote:
> ```
> interface A {
> void foo();
> }
> ```
>
> ```
> interface B extends A {
> @Override default void foo() { }
> }
> ```
>
> ```
> class C implements B { }
> ```
>
> If we compile `A.java` and `B.java` with `javac -source 8` and
> `C.java` with `-source 7` we will get the following error:
> ```
> $ javac -source 8 A.java
> $ javac -source 8 B.java
> $ javac -source 7 C.java
> C.java:1: error: C is not abstract and does not override abstract
> method foo() in A
> class C implements B { }
> ```
>
> I think this is wrong, because `foo()` is implemented as a default
> method in `B`.
The Java language circa JLS7 does not have default methods, so the
membership of C cannot possibly involve a default method inherited from
B. The Java language is backward compatible, not forward compatible.
A Java compiler that adheres to JLS7 (`-source 7`) is right to reject
C.java -- either with the error given above, or with a more
context-aware error along the lines of "C is written for Java 7, cannot
inherit default method from B".
> The following, slightly simpler example works perfectly fine, although
> it also depends on a default method in an implemented interface:
>
> ```
> interface D {
> default void bar() { }
> }
> ```
>
> ```
> class E implements D { }
> ```
>
> ```
> $ javac -source 8 D.java
> $ javac -source 7 E.java
> ```
>
> In the second example, `javac` happily accepts the default
> implementation of `bar()` from interface `D`.
It's hard to see how javac is processing class E, so I added a method
declaration `@Override public void bar() {}` to E and `javac -source 7
E.java` accepted the code. That's improper, because in Java 7 there is
no such thing as a default method in D to override from E.
I then added a method invocation `D.super.bar();` as the body of E's bar
method. In JLS8, this means "invoke my superinterface's default method".
However, in JLS7, it means "invoke my enclosing class's method", but D
isn't an enclosing class, so it's illegal (see
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.1-100-D)
-- yet `javac -source 7 E.java` accepts it anyway. Highly improper on
javac's part.
Alex
More information about the compiler-dev
mailing list