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

Ethan McCue ethan at mccue.dev
Sun Jun 2 01:28:36 UTC 2024


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/6378b3e7/attachment-0001.htm>


More information about the amber-dev mailing list