- 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.

Reply via email to