8306854: javac with '-source 7' should honor default methods in implemented Java 8 interfaces
forax at univ-mlv.fr
forax at univ-mlv.fr
Wed Apr 26 16:16:50 UTC 2023
----- Original Message -----
> From: "Volker Simonis" <volker.simonis at gmail.com>
> To: "Remi Forax" <forax at univ-mlv.fr>
> Cc: "Alex Buckley" <alex.buckley at oracle.com>, "compiler-dev" <compiler-dev at openjdk.java.net>
> Sent: Wednesday, April 26, 2023 4:10:26 PM
> Subject: Re: 8306854: javac with '-source 7' should honor default methods in implemented Java 8 interfaces
> On Tue, Apr 25, 2023 at 9:17 PM Remi Forax <forax at univ-mlv.fr> wrote:
>>
>> ----- Original Message -----
>> > From: "Alex Buckley" <alex.buckley at oracle.com>
>> > To: "compiler-dev" <compiler-dev at openjdk.java.net>
>> > Sent: Tuesday, April 25, 2023 7:09:41 PM
>> > Subject: Re: 8306854: javac with '-source 7' should honor default methods in
>> > implemented Java 8 interfaces
>>
>> > 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
>>
>> Alex, Java 8 adds a lot of default methods to the interfaces of the collection
>> API, so javac8 -source 7 could not stop each time it sees a default methods,
>> otherwise a lot of code will never have compiled. Which means that javac7
>> -source 7 and javac8 -source 7 have to have different behaviors.
>>
>> It was decided that javac8 -source 7 should skip default methods because it
>> works well with the collection API even if it does not work that well in other
>> cases as the one provided by Volker.
>
> What do you mean by "skip". 'javac8 -source 7' can make use of default
> methods quite well.
Skip the implementation part when considering overriding.
>From the POV of the compiler javac8 -source 7, a default method behave like an abstract method.
Rémi
More information about the compiler-dev
mailing list