<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body style="overflow-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div>So, that is how things are supposed to work?</div><div><br></div><div>Also, can you explain why javac does not complain about the builder.perform() invocation?</div><div>That variable is declared using the disputed parameter declaration.</div><div>If the parameter type is taken to be Thread.Builder, the call to perform should be rejected.</div><br id="lineBreakAtBeginningOfMessage"><div><br><blockquote type="cite"><div>On Dec 17, 2023, at 9:56 AM, Remi Forax <forax@univ-mlv.fr> wrote:</div><br class="Apple-interchange-newline"><div><div><div style="font-family: arial, helvetica, sans-serif; font-size: 12pt;"><div><br></div><div><br></div><hr id="zwchr" data-marker="__DIVIDER__"><div data-marker="__HEADERS__"><blockquote style="border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt;"><b>From: </b>"Alan Snyder" <javalists@cbfiddle.com><br><b>To: </b>"compiler-dev" <compiler-dev@openjdk.org><br><b>Sent: </b>Sunday, December 17, 2023 5:48:15 PM<br><b>Subject: </b>a change in javac behavior<br></blockquote></div><div data-marker="__QUOTED_TEXT__"><blockquote style="border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt;">I’m experiencing a change in behavior compiling a particular file.<br><div>The compiler is trying to match an invocation to one of two constructors for a static class defined in the same file.</div><br><div>The second constructor has a parameter of type Builder. In the past, this was interpreted as my Builder class, which is imported into this file.</div><div>That matches the invocation.</div><br><div>Now, however, the constructor parameter type is interpreted as java.lang.Thread.Builder, presumably because the static class extends Thread.</div><div>That causes a mismatch to be reported.</div><br><div>This interpretation appears to be limited to the resolution of the constructor invocation. Within the constructor, I do not get an error when the parameter</div><div>is used as an instance of my Builder class.</div><br><div>This happens in JDK 20, JDK 21, and the latest build of JDK 22.</div><div>It does not happen in JDK 17.</div></blockquote><div><br></div><div>I believe this is not a behavior change, you are experiencing the "comb" behavior, where javac will first start to match members declared inside the class hierarchy before trying to match other members.<br data-mce-bogus="1"></div><div>Here is the classical example<br data-mce-bogus="1"></div><div>class Foo {<br data-mce-bogus="1"></div><div> String name;<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div> void setName(String name) {<br data-mce-bogus="1"></div><div> this.name = name;<br data-mce-bogus="1"></div><div> }<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div> public void execute() {<br></div><div> new Thread() {<br></div><div> public void run() {<br data-mce-bogus="1"></div><div> setName("foo");<br data-mce-bogus="1"></div><div> }<br data-mce-bogus="1"></div><div> }.start();<br data-mce-bogus="1"></div><div> } <br data-mce-bogus="1"></div><div>}<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>where the method setName() inside execute() calls Thread.setName() instead of Foo.setName().<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>You code compiles with JDK 17 because Thread.Builder was introduced in 21 (19 as preview).<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><div>If you want to avoid those kind of issues, prefer delegation to inheritance.<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div><blockquote style="border-left-width: 2px; border-left-style: solid; border-left-color: rgb(16, 16, 255); margin-left: 5px; padding-left: 5px; font-weight: normal; font-style: normal; text-decoration: none; font-family: Helvetica, Arial, sans-serif; font-size: 12pt;"><br><div>The error message:</div><br><div><div> [javac] constructor Worker.Worker(@org.jetbrains.annotations.NotNull String,@org.jetbrains.annotations.NotNull SeverityLevel,@org.jetbrains.annotations.NotNull java.lang.Thread.Builder,@org.jetbrains.annotations.Nullable TaskStatusListener,@org.jetbrains.annotations.NotNull SimpleTaskReceiver<BuildResult>) is not applicable</div><div> [javac] (argument mismatch; @org.jetbrains.annotations.NotNull com.cbfiddle.releases.Builder cannot be converted to @org.jetbrains.annotations.NotNull java.lang.Thread.Builder)</div><br></div><br><div>The constructor:</div><br><div><div style="background-color: rgb(255, 255, 255); color: rgb(74, 92, 110);"><pre style="font-family: Menlo, monospace; font-size: 9pt;"><span style="color: rgb(133, 107, 70);">public </span><span style="color: rgb(167, 95, 0);">Worker</span>(<span style="color: rgb(184, 185, 111);">@NotNull </span><span style="color: rgb(73, 84, 94);">String </span><span style="color: rgb(81, 81, 81);">taskName</span><span style="color: rgb(102, 79, 61);">,<br></span><span style="color: rgb(184, 185, 111);">@NotNull </span><span style="color: rgb(73, 84, 94);">SeverityLevel </span><span style="color: rgb(81, 81, 81);">level</span><span style="color: rgb(102, 79, 61);">,<br></span><span style="color: rgb(184, 185, 111);">@NotNull </span><span style="color: rgb(81, 81, 81);">Builder builder</span><span style="color: rgb(102, 79, 61);">,<br></span><span style="color: rgb(184, 185, 111);">@Nullable </span><span style="color: rgb(81, 81, 81);">TaskStatusListener tsl</span><span style="color: rgb(102, 79, 61);">,<br></span><span style="color: rgb(184, 185, 111);">@NotNull </span><span style="color: rgb(81, 81, 81);">SimpleTaskReceiver</span><<span style="color: rgb(73, 84, 94);">BuildResult</span>> <span style="color: rgb(81, 81, 81);">r</span>)<br>{<br> <span style="color: rgb(133, 107, 70);">this</span>.<span style="color: rgb(99, 82, 107);">taskName </span>= <span style="color: rgb(81, 81, 81);">taskName</span><span style="color: rgb(96, 76, 61);">;<br></span><span style="color: rgb(133, 107, 70);">this</span>.<span style="color: rgb(99, 82, 107);">level </span>= <span style="color: rgb(81, 81, 81);">level</span><span style="color: rgb(96, 76, 61);">;<br></span><span style="color: rgb(133, 107, 70);">this</span>.<span style="color: rgb(99, 82, 107);">r </span>= <span style="color: rgb(81, 81, 81);">r</span><span style="color: rgb(96, 76, 61);">;<br></span><span style="color: rgb(133, 107, 70);">this</span>.<span style="color: rgb(99, 82, 107);">bl </span>= createBuildListener(<span style="color: rgb(81, 81, 81);">tsl</span>)<span style="color: rgb(96, 76, 61);">;<br></span><span style="color: rgb(133, 107, 70);">this</span>.<span style="color: rgb(99, 82, 107);">op </span>= () -> <span style="color: rgb(179, 141, 196);">builder</span>.perform(<span style="color: rgb(99, 82, 107);">bl</span>)<span style="color: rgb(96, 76, 61);">;<br></span><span style="color: rgb(96, 76, 61);"><br></span>setPriority(<span style="color: rgb(73, 84, 94);">Thread</span>.<span style="color: rgb(134, 109, 143); font-style: italic;">MIN_PRIORITY</span>)<span style="color: rgb(96, 76, 61);">;<br></span>}<br></pre></div></div></blockquote><div><br></div><div>regards,<br data-mce-bogus="1"></div><div>Rémi<br data-mce-bogus="1"></div><div><br data-mce-bogus="1"></div></div></div></div></div></blockquote></div><br></body></html>