<div dir="ltr"><div>Virtuous.</div><div><br></div><div>The quips about horses having fled the barn are coming, but whether they did is irrelevant; let's just make Java better now.</div><div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Sep 28, 2022 at 10:57 AM Brian Goetz <<a href="mailto:brian.goetz@oracle.com" target="_blank">brian.goetz@oracle.com</a>> wrote:<br></div><div dir="ltr" class="gmail_attr"><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div><font size="4"><font face="monospace">## Concept overload<br></font></font></div></blockquote><div><br></div><div>I like that the focus is not just on boilerplate but on the offense of forcing learners to encounter concepts they *will* need to care about but don't yet.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><font size="4"><font face="monospace"> - Relax the requirement that the class, and `main` method, be
public. Public<br>
accessibility is only relevant when access crosses packages;
simple programs<br>
live in the unnamed package, so cannot be accessed from any
other package<br>
anyway. For a program whose main class is in the unnamed
package, we can<br>
drop the requirement that the class or its `main` method be
public,<br>
effectively treating the `java` launcher as if it too resided
in the unnamed<br>
package.<br></font></font></div></blockquote><div><br></div><div>Alternative: drop the requirement altogether. Most main methods have no desire to make themselves publicly callable as `TheClass.main(args)`, but today they are forced to expose that API anyway. I feel like it would still be conceptually clean to say that `public` is really about whether other *code* can access it, not whether a VM can get to it at all.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><font size="4"><font face="monospace">
- Make the "args" parameter to `main` optional, by allowing the
`java` launcher to<br>
first look for a main method with the traditional
`main(String[])`<br>
signature, and then (if not found) for a main method with no
arguments.<br></font></font></div></blockquote><div><br></div><div>This seems to leave users vulnerable to some surprises, where the code they think is being called isn't. Why not make it a compile-time error to provide both forms?</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><font size="4"><font face="monospace">
- Make the `static` modifier on `main` optional, by allowing
the `java` launcher to<br>
invoke an instance `main` method (of either signature) by
instantiating an<br>
instance using an accessible no-arg constructor and then
invoking the `main`<br>
method on it.<br></font></font></div></blockquote><div><br></div><div>I'll give the problems I see with this, without a judgement on what should be done.</div><div><br></div><div>What's the whole idea of main? Well, it's the entry point into the program. But now it's <i>not</i> really the entry point; finding the entry point is more subtle. (Okay, I concede that static initializers are run first either way; that undercuts *some* of the strength of my argument here.)</div><div><br></div><div>Even if this is okay when I'm writing my own new program, understanding it as I go, then suppose someone else reads my program. That person has the burden of remembering to check whether `main` is static or not, and remembering that some constructor code is happening first if it's not. Classes that have both main and a constructor will be a mixture of some that call them in one order and some in the other. That's just, like, messy.</div><div><br></div><div>And is it even clear, then, why the VM shouldn't be passing `args` to the <i>constructor</i>, only hoarding it until calling `main`?<br></div><div><div><br></div></div><div>On a deep conceptual level... I'd insist that main() *is static*. It is *the* single entry point into the program; what could be more static than that? But thinking about our learner, who wrote some `main`s before learning about static. The instant they learn `static` is a keyword a method can have, they'll "know" one thing about it already: this is going to be something new that's *not* true of main(). But then they hear an explanation that fits `main` perfectly?</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><font size="4"><font face="monospace">Because excessive use of `static` is considered a code
smell, many<br>
educators encourage the pattern of "all the static `main` method
does is<br>
instantiate an instance and call an instance `main` method"
anyway.</font></font></div></blockquote><div><br></div><div>Heavy groan. In my opinion, some ideas are too misguided to take seriously.</div><div><br></div><div>The value in that practice is if instance `main` accepts parameters like `PrintStream` and `Console`, and static main passes in `System.out` and `System.console()`. That makes all your actual program logic unit-testable. Great! This actually strikes directly at the heart of what the entire problem with `static` is! But this isn't the case you're addressing.</div><div><br></div><div>Static methods are not a code smell! Static methods that ought to be overrideable by one of their argument types (Collections.sort()), sure. Static mutable state is a code smell, definitely -- but a method that touches that state is equally problematic whether it itself is static or not. There are some code smells around `static`, but `static` itself is fresh and flowery.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><font size="4"><font face="monospace">(Further, allowing the `main` method to be an
instance method<br>
means that it could be inherited from a superclass, which is
useful for simple<br>
frameworks such as test runners or service frameworks.)<br></font></font></div></blockquote><div><br></div><div>This does not give me a happy feeling. Going into it is a deep discussion though.</div><div><br></div><div>Rest of the response coming soon, I hope.</div></div><div><br></div><div>Just to mention one additional idea. We could permit `main` to optionally return `int`, becoming the default exit status if `exit` is never called. Seems elegant for the rare cases where you care about exit status, but (a) would this feature get in the way in *any* sense for the vast majority of cases that don't care, or (b) are the cases that care just way too rare for us to worry about?</div><div><div><br></div></div><div>I'm not sure about (a). But (b) kinda seems like a yes.</div><div><br></div>-- <br><div dir="ltr"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div style="line-height:1.5em;padding-top:10px;margin-top:10px;color:rgb(85,85,85);font-family:sans-serif"><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(213,15,37);padding-top:2px;margin-top:2px">Kevin Bourrillion |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(51,105,232);padding-top:2px;margin-top:2px"> Java Librarian |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(0,153,57);padding-top:2px;margin-top:2px"> Google, Inc. |</span><span style="border-width:2px 0px 0px;border-style:solid;border-color:rgb(238,178,17);padding-top:2px;margin-top:2px"> <a href="mailto:kevinb@google.com" target="_blank">kevinb@google.com</a></span></div></div></div></div></div></div></div></div>