Default interface methods aren't considered abstract method implementations
Pavel Rappo
pavel.rappo at gmail.com
Mon Feb 10 10:48:24 UTC 2025
Could your initial example be directly addressed by 8.4.8.4?
On Mon 10 Feb 2025 at 09:44, Attila Szegedi <szegedia at gmail.com> wrote:
> Hi both Chen and Pavel,
>
> Thank you both for answering! I was not specifically asking Brian, of
> course, that’s why there’s a wink next to it :-)
> I now scoured JLS 23, specifically:
>
> ----
> 8.1.1.1. abstract Classes
>
> A class C has abstract methods if either of the following is true:
>
> Any of the member methods (§8.2) of C - either declared or inherited - is
> abstract.
>
> Any of C's superclasses has an abstract method declared with package
> access, and there exists no method that overrides the abstract method from
> C or from a superclass of C.
>
> 8.2. Class Members
>
> The members of a class are all of the following:
>
> Members inherited from its direct superclass type (§8.1.4), except in the
> class Object, which has no direct superclass type
>
> Members inherited from any direct superinterface types (§8.1.5)
>
> Members declared in the body of the class (§8.1.7)
>
> 8.1.5. Superinterfaces:
>
> Each default method (§9.4.3) of a superinterface of the class may
> optionally be overridden by a method in the class; if not, the default
> method is typically inherited and its behavior is as specified by its
> default body.
> -----
>
> And nothing in there tells me unambiguously that my example should’t work
> (the last quoted sentence from 8.1.1.1 is weird, but adding “public” to
> declaration of “m” circumvents it and it still doesn’t compile.) There are
> few phrases that seem open to interpretation though: "default method is
> _typically_ inherited” (typically is doing heavy lifting here: sometimes it
> isn’t?) and “_any of the member methods_ (§8.2) of C - either declared or
> inherited - is abstract" (are A.m() and F.m() treated as separate member
> methods at this stage despite identical signatures?)
>
> Again, I’m not arguing current javac behavior is wrong, just trying to
> understand why is it right. I actually hit this in an IRL refactoring – had
> several classes that both extended an abstract class (A) and implemented an
> interface (F), and all these classes had the same implementation for an
> abstract method (m) that was actually semantically related to F and it felt
> like a good example of DRY to implement the method only once as a default
> in F. (Yes, I could create an interim class AF and move the implementation
> there, but this felt like it would’ve been a good use of an interface as a
> mixin.)
>
> I wonder if I recreated the example in bytecode directly whether the JVM
> would load the class successfully (I might need to attempt to also call the
> method) or would I get some kind of IncompatibleClassChangeError.
>
> Attila.
>
> On 2025. Feb 10. at 1:58:32, Chen Liang <liangchenblue at gmail.com> wrote:
>
>> Hello guys, amber is for new language features. Questions with java
>> compilation or JLS/JVMS belong to the compiler group.
>>
>> That said, I believe this behavior is most likely a preservation of
>> method resolution, that for instance methods, methods from superclass have
>> higher priority than methods from interfaces. For example, before Java 8,
>> static methods could not be defined in interfaces; and when they were added
>> in 8, resolution rule states that they aren't shadowed to child types, so
>> classes cannot "inherit" interface static methods, unlike interface static
>> fields.
>>
>> Another fun fact is that superinterface fields take precedence in
>> resolution over superclass fields. Also a legacy from old Java, but I don't
>> think that is going to be changed to make things "consistent".
>>
>> Regards,
>> Chen Liang
>>
>> On Sun, Feb 9, 2025 at 4:26 PM Pavel Rappo <pavel.rappo at gmail.com> wrote:
>>
>>> Attila,
>>>
>>> Come to think of it, we should use some other, more narrowly focused,
>>> mailing list. Apologies to subscribers of this list. Since lambda-dev
>>> is defunct now, perhaps we could use compiler-dev, amber-dev, or
>>> core-libs-dev instead. I'm voting for amber-dev, where Brian mostly
>>> resides these days.
>>>
>>> -Pavel
>>>
>>> On Sun, Feb 9, 2025 at 10:12 PM Pavel Rappo <pavel.rappo at gmail.com>
>>> wrote:
>>> >
>>> > You are not specifically asking Brian, are you? If so, sorry for
>>> replying.
>>> >
>>> > My humble take is that the default method is something to use when
>>> > there's nothing else there. When there's something, even if it's
>>> > abstract, we use that. So, a default method is a minimally interfering
>>> > fallback/extension scenario, if you will.
>>> >
>>> > That abstract A.m() effectively replaces default F.m() in C as if
>>> > F.m() were never there. If F.m() were allowed to provide
>>> > implementation for A.m() in C, then some uncompliable code could
>>> > suddenly become compilable and operational at runtime.
>>> >
>>> > -Pavel.
>>> >
>>> > On Sun, Feb 9, 2025 at 9:04 PM Attila Szegedi <szegedia at gmail.com>
>>> wrote:
>>> > >
>>> > > Hey folks,
>>> > >
>>> > > I found a somewhat puzzling behavior: default interface methods
>>> aren't considered abstract method implementations. Trying to compile this
>>> minimal reproducer:
>>> > >
>>> > > ------ C.java ------
>>> > > abstract class A {
>>> > > abstract void m();
>>> > > }
>>> > >
>>> > > interface F {
>>> > > default void m() {}
>>> > > }
>>> > >
>>> > > class C extends A implements F {}
>>> > > ------ C.java ------
>>> > >
>>> > > $ javac C.java
>>> > > C.java:9: error: C is not abstract and does not override abstract
>>> method m() in A
>>> > > class C extends A implements F {
>>> > > ^
>>> > > 1 error
>>> > >
>>> > > I can accept this being valid according to JLS today (I tried with
>>> 11, 21, and 23.) I admit this is one of rare occasions when I didn't go
>>> scouring the JLS to figure out what exactly prevents the compiler from
>>> accepting F.m() as implementation of A.m() in C. I'm wondering though if
>>> this isn't something that could be improved upon in the future. (I'm sure
>>> there's a gotcha somewhere. Right, Brian? ;-) )
>>> > >
>>> > > Have a great day,
>>> > > Attila.
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/compiler-dev/attachments/20250210/5fcd6663/attachment-0001.htm>
More information about the compiler-dev
mailing list