<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <p>Hi Attila,</p>
    <p>FYI, some of the documentation for Project Lambda</p>
    <p>   <a class="moz-txt-link-freetext" href="https://openjdk.org/projects/lambda/">https://openjdk.org/projects/lambda/</a></p>
    <p>hints at the general design rationale here. For example, the
      default methods (nee "defender methods") doc [1] discusses "favor
      classes over interfaces" in method resolution and "if multiple
      methods from interfaces, the user has to choose."<br>
      <br>
      HTH,<br>
    </p>
    <p>-Joe</p>
    <p>[1]
      <a class="moz-txt-link-freetext" href="https://cr.openjdk.org/~briangoetz/lambda/Defender%20Methods%20v4.pdf">https://cr.openjdk.org/~briangoetz/lambda/Defender%20Methods%20v4.pdf</a>
    </p>
    <div class="moz-cite-prefix">On 2/10/2025 1:44 AM, Attila Szegedi
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:CAMYVXdtEavKSZAoPDZPaXkjjEsund=LU_jNaUWj1WtXPhmQCXA@mail.gmail.com">
      
      <div dir="ltr"> Hi both Chen and Pavel,</div>
      <div dir="ltr"><br>
      </div>
      <div dir="ltr">Thank you both for answering! I was not
        specifically asking Brian, of course, that’s why there’s a wink
        next to it :-)</div>
      <div dir="ltr">I now scoured JLS 23, specifically:</div>
      <div dir="ltr"><br>
      </div>
      <div dir="ltr">
        <div dir="ltr">----</div>
        <div dir="ltr">8.1.1.1. abstract Classes</div>
        <div><br>
        </div>
        <div>
          <div>A class C has abstract methods if either of the following
            is true:</div>
          <div><br>
          </div>
          <div>Any of the member methods (§8.2) of C - either declared
            or inherited - is abstract.</div>
          <div><br>
          </div>
          <div>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.</div>
        </div>
        <div><br>
        </div>
        <div>
          <div>8.2. Class Members</div>
          <div><br>
          </div>
          <div>The members of a class are all of the following:</div>
          <div><br>
          </div>
          <div>Members inherited from its direct superclass type
            (§8.1.4), except in the class Object, which has no direct
            superclass type</div>
          <div><br>
          </div>
          <div>Members inherited from any direct superinterface types
            (§8.1.5)</div>
          <div><br>
          </div>
          <div>Members declared in the body of the class (§8.1.7)</div>
        </div>
        <div><br>
        </div>
        <div>
          <div>8.1.5. Superinterfaces:</div>
          <div><br>
          </div>
          <div>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.<br>
          </div>
        </div>
        <div>-----<br>
        </div>
        <div dir="ltr"><br>
        </div>
        <div dir="ltr">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?) </div>
        <div dir="ltr"><br>
        </div>
        <div dir="ltr">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.)</div>
        <div dir="ltr"><br>
        </div>
        <div dir="ltr">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.</div>
        <div dir="ltr"><br>
        </div>
        <div dir="ltr">Attila.</div>
        <div dir="ltr"><br>
        </div>
      </div>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">On 2025. Feb 10. at 1:58:32,
          Chen Liang <<a href="mailto:liangchenblue@gmail.com" moz-do-not-send="true" class="moz-txt-link-freetext">liangchenblue@gmail.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" type="cite">
          <div dir="ltr">Hello guys, amber is for new language features.
            Questions with java compilation or JLS/JVMS belong to the
            compiler group.
            <div><br>
            </div>
            <div>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.</div>
            <div><br>
            </div>
            <div>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".</div>
            <div><br>
            </div>
            <div>Regards,</div>
            <div>Chen Liang</div>
          </div>
          <br>
          <div class="gmail_quote gmail_quote_container">
            <div dir="ltr" class="gmail_attr">On Sun, Feb 9, 2025 at
              4:26 PM Pavel Rappo <<a href="mailto:pavel.rappo@gmail.com" moz-do-not-send="true" class="moz-txt-link-freetext">pavel.rappo@gmail.com</a>>
              wrote:<br>
            </div>
            <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Attila,<br>
              <br>
              Come to think of it, we should use some other, more
              narrowly focused,<br>
              mailing list. Apologies to subscribers of this list. Since
              lambda-dev<br>
              is defunct now, perhaps we could use compiler-dev,
              amber-dev, or<br>
              core-libs-dev instead. I'm voting for amber-dev, where
              Brian mostly<br>
              resides these days.<br>
              <br>
              -Pavel<br>
              <br>
              On Sun, Feb 9, 2025 at 10:12 PM Pavel Rappo <<a href="mailto:pavel.rappo@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">pavel.rappo@gmail.com</a>>
              wrote:<br>
              ><br>
              > You are not specifically asking Brian, are you? If
              so, sorry for replying.<br>
              ><br>
              > My humble take is that the default method is
              something to use when<br>
              > there's nothing else there. When there's something,
              even if it's<br>
              > abstract, we use that. So, a default method is a
              minimally interfering<br>
              > fallback/extension scenario, if you will.<br>
              ><br>
              > That abstract A.m() effectively replaces default
              F.m() in C as if<br>
              > F.m() were never there. If F.m() were allowed to
              provide<br>
              > implementation for A.m() in C, then some uncompliable
              code could<br>
              > suddenly become compilable and operational at
              runtime.<br>
              ><br>
              > -Pavel.<br>
              ><br>
              > On Sun, Feb 9, 2025 at 9:04 PM Attila Szegedi <<a href="mailto:szegedia@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">szegedia@gmail.com</a>>
              wrote:<br>
              > ><br>
              > > Hey folks,<br>
              > ><br>
              > > I found a somewhat puzzling behavior: default
              interface methods aren't considered abstract method
              implementations. Trying to compile this minimal
              reproducer:<br>
              > ><br>
              > > ------ C.java ------<br>
              > > abstract class A {<br>
              > >   abstract void m();<br>
              > > }<br>
              > ><br>
              > > interface F {<br>
              > >   default void m() {}<br>
              > > }<br>
              > ><br>
              > > class C extends A implements F {}<br>
              > > ------ C.java ------<br>
              > ><br>
              > > $ javac C.java<br>
              > > C.java:9: error: C is not abstract and does not
              override abstract method m() in A<br>
              > > class C extends A implements F {<br>
              > > ^<br>
              > > 1 error<br>
              > ><br>
              > > 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? ;-) )<br>
              > ><br>
              > > Have a great day,<br>
              > >   Attila.<br>
            </blockquote>
          </div>
        </blockquote>
      </div>
    </blockquote>
  </body>
</html>