Do we really need an implicit "import static java.io.IO.*"?

David Alayachew davidalayachew at gmail.com
Sun Jun 2 02:46:30 UTC 2024


Heh, we're both unpaid :P I tutor folks from my university and church, as
well as a couple of friends and family. Slowing down now though because of
workload at work.

But back to the point.

> I think the problem is that without static "global"
> fields are always accessible and all the nested classes
> in their program are instansable from anywhere.
>
> Once you have a static method, a method on a record, a
> method on an enum, or a static inner class this is no
> longer the case.

Apologies, maybe I missed the memo. I have been out of touch with this (and
all other JEP's) because of my insane workload for the past couple of
months.

Why would adding a static method change any of the logic?

I took your example in Java 22, added a static method, and everything
worked dandy.

Am I missing something?

On Sat, Jun 1, 2024 at 9:28 PM Ethan McCue <ethan at mccue.dev> wrote:

> I am also basically just a tutor, just unpaid.
>
> I think the problem is that without static "global" fields are always
> accessible and all the nested classes in their program are instansable from
> anywhere.
>
> Once you have a static method, a method on a record, a method on an enum,
> or a static inner class this is no longer the case.
>
> Trite example of the mechanics I'm referencing:
>
> int count = 0;
>
> class A {
>     void b() {
>          count++;
>          c();
>          new D();
>     }
> }
>
> void c() {
>     println("" + count);
> }
>
> class D {}
>
> void main() {
>     new A().b();
> }
>
> So when you show static methods, I think you need to understand why
> count++; and c(); and new D(); would not function.
>
> That requires knowing that you are actually in an anonymous class. That
> requires we get past import static java.io.IO. That's the loop.
>
>
>
> On Sat, Jun 1, 2024, 8:59 PM David Alayachew <davidalayachew at gmail.com>
> wrote:
>
>> Maybe I am missing something, but a static import seems like the natural
>> next step to teaching a student who made it that far.
>>
>> If a student feels the need to break out of the bounds of an implicitly
>> declared class, they must first understand what a class is going to save
>> them from. In this case, it is allowing code they right to be reused else
>> where.
>>
>> I am only a tutor, not a full-blown teacher, but when tutoring folks in
>> this exact subject, I would always start by taking one of their projects,
>> ask them to tweak in a subtle, but difficult way, then let them run
>> headfirst into the problem. Once they start to feel the strain, I would
>> introduce them to the concepts of classes.
>>
>> I would start by showing them how to create a simple pure function,
>> similar to java.lang.Math. From there, we would make a few pure functions
>> that are unrelated to their current task, and then have them get
>> comfortable with that concept.
>>
>> Then, we would make another pure function that is being done repeatedly
>> in their "JumboClass1" and "JumboClass2", and then have them get
>> comfortable using this helper method in both versions.
>>
>> In my mind, this is naturally where the student would discover that they
>> need to do a static import. In which case, they are in the middle of
>> understanding a class, they understand imports, and they understand static
>> methods fairly well. So, a static import has been well prepared for them.
>>
>> For me, this is a neat and clean introduction. Maybe I am missing
>> something?
>>
>> On Sat, Jun 1, 2024 at 6:43 PM Ron Pressler <ron.pressler at oracle.com>
>> wrote:
>>
>>> Hi.
>>>
>>> Without getting into the merits of not implicitly importing anything,
>>> let me just point out that the following is a valid program under the
>>> current JEP:
>>>
>>>     void main() {
>>>         IO.println(“Hello, world!”);
>>>     }
>>>
>>> As is this one:
>>>
>>>     import module java.base;
>>>
>>>     void main() {
>>>         IO.println(“Hello, world!”);
>>>     }
>>>
>>> In other words, the fact that there are implicit imports doesn’t mean
>>> that you can’t ignore them or add them explicitly. if you find teaching
>>> this to be easier, you can. So even if you don’t find implicit imports
>>> helpful, they may be helpful to other teachers, who may not want to start
>>> with some import incantation that necessarily implies some
>>> programming-in-the-large concept.
>>>
>>> But I think that your unease mostly stems from the extra magic that
>>> implicit classes enjoy, and which isn’t strictly necessitated by their
>>> primary quality of being implicitly declared classes, and that extra magic
>>> differentiates them from regular compilation units along some other axis;
>>> is that right?
>>>
>>> — Ron
>>>
>>>
>>>
>>> > On 1 Jun 2024, at 23:14, Ethan McCue <ethan.mccue at lumanu.com> wrote:
>>> >
>>> > Hi all,
>>> >
>>> > I'm following the development of JEP 477[1] and I feel the need to
>>> question the impetus for the implicit static imports.
>>> >
>>> > As of now[2] any program like this
>>> >
>>> > void main() {
>>> >     println("Hello, world");
>>> > }
>>> >
>>> > Is equivalent to
>>> >
>>> > import static java.io.IO.print;
>>> > import static java.io.IO.println;
>>> > import static java.io.IO.writeln;
>>> >
>>> > import module java.base;
>>> >
>>> > final class Main {
>>> >     void main() {
>>> >         println("Hello, world");
>>> >     }
>>> > }
>>> >
>>> > Where all the methods in java.io.IO delegate to newly added
>>> equivalent methods in java.io.Console.[3]
>>> >
>>> > Aside from muddying that API up (now there is readln and readLine +
>>> println and printLine which...what) I'm still concerned on how those
>>> implicit imports will affect the transition to named classes.
>>> >
>>> > Assume we start a student out here
>>> >
>>> > void main() {
>>> >     println("Hello, world");
>>> > }
>>> >
>>> > You can get through conditionals, loops, variables, methods, and
>>> return types before touching classes or access specifiers.
>>> >
>>> > int compute() {
>>> >     int total = 0;
>>> >     for (int i = 0; i < 10; i++) {
>>> >         total += i;
>>> >     }
>>> >     return total;
>>> > }
>>> >
>>> > void main() {
>>> >     println("Hello: " + compute());
>>> > }
>>> >
>>> > 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."
>>> >
>>> > enum Pirate {
>>> >    BLACKBEARD,
>>> >    OTHER
>>> > }
>>> >
>>> > record Pos(int x, int y) {}
>>> >
>>> > Pos treasure(Pirate pirate) {
>>> >     switch (pirate) {
>>> >         case BLACKBEARD ->
>>> >             return new Pos(5, 5);
>>> >         case OTHER ->
>>> >             return new Pos(0, 0);
>>> >     }
>>> > }
>>> >
>>> > void main() {
>>> >     println(treasure(Pirate.OTHER));
>>> > }
>>> >
>>> > 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.
>>> >
>>> > As originally pitched, this transition would have just meant wrapping
>>> the whole program in class Main {}, but now to make the transition from
>>> >
>>> > void main() {
>>> >     // Arbitrary code
>>> > }
>>> >
>>> > to
>>> >
>>> > class Main {
>>> >     void main() {
>>> >         // Arbitrary code
>>> >     }
>>> > }
>>> >
>>> > In a robust way, you need to add those imports to the top. You can
>>> skip the final since the semantics of extension haven't been relevant yet.
>>> >
>>> > import static java.io.IO.*;
>>> >
>>> > import module java.base;
>>> >
>>> > class Main {
>>> >     void main() {
>>> >         // Arbitrary code
>>> >     }
>>> > }
>>> >
>>> > My gripe is that the concepts introduced here - static, module, and *
>>> imports  - would have had no place to be introduced earlier.
>>> >
>>> > 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.
>>> >
>>> > // For every program up until this, they could freely access this from
>>> anywhere
>>> > int count = 0;
>>> >
>>> > // And they could freely make an instance of any inner class
>>> > class Other {}
>>> >
>>> > class Pos {
>>> >     static Pos of(int x, int y) {
>>> >         // So the rules they are used to don't apply anymore
>>> >         // and the explanation as to why really lies *after* they
>>> understand
>>> >         // what an anonymous main class is and does
>>> >         // ...
>>> >     }
>>> > }
>>> >
>>> > void main() {
>>> >    // ...
>>> > }
>>> >
>>> > If you have folks *use* static methods that is fine - the hand-waving
>>> of Math.max doesn't seem to trip anyone up - but I can't figure out how to
>>> topologically sort topics such that import static makes any sense before
>>> going through multi-file programs.
>>> >
>>> > I have a similar concern with import module, 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.
>>> >
>>> > Just as a hypothetical, say java.io.IO was java.lang.IO. No new
>>> import rules needed and now IO is available to all programs.
>>> >
>>> > void main() {
>>> >     IO.printLine("Hello, world");
>>> > }
>>> >
>>> > While this does introduce something not explained - static method
>>> access - it feels easier to hand-wave away than import static java.io.IO.*;
>>> would be. It calls the printLine method, it comes from IO. IO means
>>> "Input/Output". That's a workable metaphor and can be glanced over in the
>>> same way as Math.max
>>> >
>>> > The transition from here to classes can again be "it's the same as if
>>> you had class Main {} around it" instead of "it's the same as if you had
>>> class Main {} 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."
>>> >
>>> > Also, IO. feels like a different kind of unexplained boilerplate than
>>> public static void main(String[] args) {}. 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 IO they are
>>> in that moment producing output and will soon take input.
>>> >
>>> > What am I overlooking?
>>> >
>>> >
>>> > [1]: https://openjdk.org/jeps/477
>>> > [2]:
>>> https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/IO.html
>>> > [3]
>>> https://download.java.net/java/early_access/jdk23/docs/api/java.base/java/io/Console.html#print(java.lang.Object)
>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20240601/27238736/attachment-0001.htm>


More information about the amber-dev mailing list