<div dir="ltr">Hi all,<br><br>I'm following the development of JEP 477[1] and I feel the need to question the impetus for the implicit static imports.<br><br>As of now[2] any program like this<br><br><font face="monospace">void main() {<br>    println("Hello, world");<br>}<br></font><br>Is equivalent to<br><br><font face="monospace">import static java.io.IO.print;</font><br><font face="monospace">import static java.io.IO.println;</font><br><font face="monospace">import static java.io.IO.writeln;<br><br>import module java.base;<br><br>final class Main {<br>    void main() {<br>        println("Hello, world");<br>    }<br>}</font><br><br>Where all the methods in <font face="monospace"><a href="http://java.io.io/" target="_blank">java.io.IO</a></font><font face="arial, sans-serif"> delegate to newly added equivalent methods in </font><font face="monospace">java.io.Console</font><font face="arial, sans-serif">.[3]<br></font><br>Aside from muddying that API up (now there is <font face="monospace">readln</font><font face="arial, sans-serif"> and </font><font face="monospace">readLine + println</font><font face="arial, sans-serif"> and </font><font face="monospace">printLine</font><font face="arial, sans-serif"> which...what) I'm still concerned on how those implicit imports will affect the transition to named classes.<br></font><br>Assume we start a student out here<br><br><font face="monospace">void main() {<br>    println("Hello, world");<br>}<br></font><br>You can get through conditionals, loops, variables, methods, and return types before touching classes or access specifiers.<div><br><font face="monospace">int compute() {<br>    int total = 0;<br>    for (int i = 0; i < 10; i++) {<br>        total <a class="gmail_plusreply" id="m_-8825103199311683501plusReplyChip-1">+= i;</a><br>    }<br>    return total;<br>}<br><br></font></div><div><font face="monospace">void main() {<br>    println("Hello: " + compute());<br>}</font><br><br>You can even talk about records and enums in a hand wavey way. Enums are "one of these options", Records are "if you want to return two things."<br><br><div><span style="font-family:monospace">enum Pirate {</span><br style="font-family:monospace"><span style="font-family:monospace">   BLACKBEARD,</span><br style="font-family:monospace"><span style="font-family:monospace">   OTHER</span><br style="font-family:monospace"><span style="font-family:monospace">}</span><font face="monospace"><br><br>record Pos(int x, int y) {}<br><br>Pos treasure(</font><span style="font-family:monospace">Pirate pirate</span><span style="font-family:monospace">) {<br>    switch (pirate) {<br></span><span style="font-family:monospace">        case BLACKBEARD -><br>            return new Pos(5, 5);</span><span style="font-family:monospace"><br></span><span style="font-family:monospace">        case OTHER -><br>            return new Pos(0, 0);</span><span style="font-family:monospace"><br>    }</span></div><div><font face="monospace">}<br><br></font></div><div><font face="monospace">void main() {</font><br><font face="monospace">    println(treasure(Pirate.OTHER));</font><br><font face="monospace">}</font><br><br><font face="arial, sans-serif">So it is reasonable for a student to have made a relatively complex program before having to get to that point, but I think you do need to explain what exactly is going on with the anonymous main class when you introduce multi file programs.<br></font><br><font face="arial, sans-serif">As originally pitched, this transition would have just meant wrapping the whole program in </font><font face="monospace">class Main {}</font><font face="arial, sans-serif">, but now to make the transition from<br></font><br><font face="monospace">void main() {<br>    // Arbitrary code<br>}</font><br><br>to <br><br><font face="monospace">class Main {<br>    void main() {<br></font><span style="font-family:monospace">        // Arbitrary code</span><font face="monospace"><br>    }<br>}<br></font><br>In a robust way, you need to add those imports to the top. You can skip the <font face="monospace">final</font><font face="arial, sans-serif"> since the semantics of extension haven't been relevant yet.<br></font><br><font face="monospace">import static java.io.IO.*;</font><font face="monospace"><br><br>import module java.base;<br><br>class Main {<br>    void main() {<br>        </font><span style="font-family:monospace">// Arbitrary code</span><font face="monospace"><br>    }<br>}<br></font><br>My gripe is that the concepts introduced here - <font face="monospace">static</font><font face="arial, sans-serif">, </font><font face="monospace">module</font><font face="arial, sans-serif">, and </font><font face="monospace">* imports</font><font face="arial, sans-serif">  - would have had no place to be introduced earlier.<br></font><br>If you have folks write static methods on inner classes, the metaphor of a "global field" that otherwise exists in the simple-main world goes away.<br><br><font face="monospace">// For every program up until this, they could freely access this from anywhere<br>int count = 0;<br><br>// And they could freely make an instance of any inner class<br>class Other {}<br><br>class Pos {<br>    static Pos of(int x, int y) {<br>        // So the rules they are used to don't apply anymore<br>        // and the explanation as to why really lies *after* they understand<br>        // what an anonymous main class is and does<br>        // ...<br>    }<br>}<br><br>void main() {<br>   // ... <br>}</font><br><br>If you have folks *use* static methods that is fine - the hand-waving of <font face="monospace">Math.max</font> doesn't seem to trip anyone up - but I can't figure out how to topologically sort topics such that <font face="monospace">import static</font> makes any sense before going through multi-file programs. <br><br>I have a similar concern with <font face="monospace">import module</font><font face="arial, sans-serif">, but that can be hand waved as "gets you everything from this library" so I am less concerned. Still don't fully understand the desire to have it be implicit, but less concerned.</font><font face="arial, sans-serif"> </font><br><br>Just as a hypothetical, say <font face="monospace"><a href="http://java.io.IO">java.io.IO</a></font><font face="arial, sans-serif"> was </font><font face="monospace"><a href="http://java.lang.IO">java.lang.IO</a></font><font face="arial, sans-serif">. No new import rules needed and now </font><font face="monospace">IO</font><font face="arial, sans-serif"> is available to all programs.<br></font><br><font face="monospace">void main() {<br>    IO.printLine("Hello, world");<br>}<br></font><br>While this does introduce something not explained - static method access - it feels easier to hand-wave away than <span style="font-family:monospace">import static java.io.IO.*;</span><font face="arial, sans-serif"> would be. It calls the printLine method, it comes from </font><font face="monospace">IO. IO</font><font face="arial, sans-serif"> means "Input/Output". That's a workable metaphor and can be glanced over in the same way as </font><font face="monospace">Math.max</font><br><br>The transition from here to classes can again be "it's the same as if you had <font face="monospace">class Main {}</font> around it" instead of "it's the same as if you had <font face="monospace">class Main {}</font> around it and these imports. A static import imports a static method. A static method is a method attached to the class itself instead of the instance.... etc."<br><br>Also, <font face="monospace">IO.</font><font face="arial, sans-serif"> feels like a different kind of unexplained boilerplate than </font><font face="monospace">public static void main(String[] args) {}</font><font face="arial, sans-serif">. There is a lot of ground you need to cover before access modifiers, static methods, or command line arguments make any sort of sense. When you have someone write </font><font face="monospace">IO</font><font face="arial, sans-serif"> they are in that moment producing output and will soon take input.</font><br><br>What am I overlooking? <br><br></div><br>[1]: <a href="https://openjdk.org/jeps/477" target="_blank">https://openjdk.org/jeps/477</a><br>[2]: <a href="https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/IO.html" target="_blank">https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/IO.html</a><br>[3] <a href="https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/Console.html#print(java.lang.Object)" target="_blank">https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/Console.html#print(java.lang.Object)</a></div></div>