Paving the on-ramp

Brian Goetz brian.goetz at oracle.com
Wed Sep 28 20:10:02 UTC 2022


>
>      - Relax the requirement that the class, and `main` method, be
>     public.  Public
>        accessibility is only relevant when access crosses packages;
>     simple programs
>        live in the unnamed package, so cannot be accessed from any
>     other package
>        anyway.  For a program whose main class is in the unnamed
>     package, we can
>        drop the requirement that the class or its `main` method be public,
>        effectively treating the `java` launcher as if it too resided
>     in the unnamed
>        package.
>
>
> 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.

I think we're saying the same thing; main need not be public.

>
>      - Make the "args" parameter to `main` optional, by allowing the
>     `java` launcher to
>        first look for a main method with the traditional `main(String[])`
>        signature, and then (if not found) for a main method with no
>     arguments.
>
>
> 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?

Currently, the treatment of methods called "main" is "and also"; it is a 
valid method, *and also* (if it has the right shape) can be used as a 
main entry point.  Making this an error would take some valid programs 
and make them invalid, which seems a shift in the interpretation of the 
magic name "main".  A warning is probably reasonable though.

>
>      - Make the `static` modifier on `main` optional, by allowing the
>     `java` launcher to
>        invoke an instance `main` method (of either signature) by
>     instantiating an
>        instance using an accessible no-arg constructor and then
>     invoking the `main`
>        method on it.
>
>
> 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?

John likes to say "static has messed up every job we've ever given it", 
and while that seems an exaggeration at first, often turns out to be 
surprisingly accurate.  One subtle thing it messes up here is that one 
cannot effectively inherit a main() method.  But inheriting main() is 
super useful!  Consider a TestCase class in a test framework, or an 
AbstractService class in a services framework.  If the abstract class 
can provide the main() method, then every test case or service _is also 
a program_, one which runs that test case or service.

But, there is cheese-moving here.  In the old model, "main" is just a 
disembodied method, which only accidentally lives in a class, and drags 
the class along for the ride.   In this model, main-ness moves up the 
stack, becoming a property of a class, not just something a class has.

This tension is evident in JLS 12, which defines the interaction with 
main.  It is full of wiggle words, because it is trying to pretend that 
Java has no concept of "program", just classes, but at the same time, 
there has to be a way to get the computation started.  The JLS tries to 
pretend that "program" is defined almost extralinguistically (by appeal 
to an unspcified launcher program that exists outside of the language), 
but nearly trips over its own feet trying to have it both ways.

The debate among educators about whether main should be allowed to do 
anything it wants, or should only instantiate an object and call a 
single method, illustrates this tension.  So what is really going on 
here is bringing the notion of "program" to classes in a less 
nailed-on-the-side way.

> 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?
>
> I'm not sure about (a). But (b) kinda seems like a yes.
>

Considered this (since C lets you do this.)   Since Java doesn't let you 
overload on return types, we have the option to do this later without 
making the search order any more complicated, so I left it out.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-observers/attachments/20220928/de998c94/attachment-0001.htm>


More information about the amber-spec-observers mailing list