<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body>
    <font size="4"><font face="monospace">One thing that this forces us
        to confront, in some manner or other, are the rules about the
        relationship between the file name and the class name, which are
        spread out in a few different places.  <br>
        <br>
        The compiler issues an error when a top-level *public* class
        does not match the file it is in.  Order is irrelevant; the
        following are valid Foo.java files:<br>
        <br>
        --<br>
        public class Foo { }<br>
        class Bar { }<br>
        --<br>
        class Foo { }<br>
        class Bar { }<br>
        --<br>
        class Bar { }<br>
        public class Foo { }<br>
        --<br>
        <br>
        but the following are illegal for Foo.java:<br>
        <br>
        --<br>
        public class Foo { }<br>
        public class Bar { }<br>
        --<br>
        public class Bar { }<br>
        --<br>
        <br>
        The standard class loader implementation enforces that a class
        file X.class must contain a class called X (javap will warn
        about this too.)  When compiling code in-memory, the javac
        "FileManager" abstraction still requires a "file name" for each
        source unit being compiled, even if there is no actual file.  <br>
        <br>
        <br>
        The prototype implementation we have does infer a class name
        from the file name in the obvious way; we just don't enter it
        into the symbol table.  But, if you put this in Foo.java:<br>
        <br>
        --<br>
        void main() { }<br>
        --<br>
        <br>
        You'll get a Foo.class with class Foo in it, and if you put that
        class file on the class path, *other* classes can instantiate it
        by name.  So the prototype is currently in a half-here,
        half-there situation.  It is probably overkill to try to have
        some ACC_UNNAMED marking to prevent this.  So we might accept
        this odd state, or we might embrace it as Guy suggests, and go
        ahead and enter Foo in the symbol table, and even let people
        declare constructors.  That means that the name "unnamed class"
        would no longer be an accurate name (a shame, since its friends
        "unnamed module" and "unnamed package" have been saving it a
        seat.)  This is a workable direction, though not a forced move. 
        <br>
        <br>
        <br>
        The other connection point with the file name is the one Tagir
        brought up, which is the effect of accidentally putting a method
        or field outside the braces.  If you have a class<br>
        <br>
        --<br>
        class Foo { }<br>
        void x() { }<br>
        --<br>
        <br>
        today, this is an error; under this proposal, this becomes a
        valid unnamed class with a *nested* class Foo, which may not be
        what was meant.  We can reduce the possibility of this by
        issuing a warning/error if an unnamed class has a "top-level"
        nested class whose name matches the file.  This seems reasonably
        consistent with the existing rules constraining file names and
        class names.  If we combined this with the previous move, this
        becomes "An unnamed class cannot have a top-level nested class
        of the same name".  <br>
        <br>
        <br>
      </font></font><br>
    <div class="moz-cite-prefix">On 9/28/2022 1:57 PM, Brian Goetz
      wrote:<br>
    </div>
    <blockquote type="cite" cite="mid:1b6200d3-a7a6-6479-e8ab-d932eedbceb1@oracle.com">
      
      <font size="4"><font face="monospace">At various points, we've
          explored the question of which program elements are most and
          least helpful for students first learning Java.  After
          considering a number of alternatives over the years, I have a
          simple proposal for smoothing the "on ramp" to Java
          programming, while not creating new things to unlearn.  <br>
          <br>
          Markdown source is below, HTML will appear soon at: <br>
          <br>
              <a class="moz-txt-link-freetext" href="https://openjdk.org/projects/amber/design-notes/on-ramp" moz-do-not-send="true">https://openjdk.org/projects/amber/design-notes/on-ramp</a><br>
          <br>
          <br>
          # Paving the on-ramp<br>
          <br>
          Java is one of the most widely taught programming languages in
          the world.  Tens<br>
          of thousands of educators find that the imperative core of the
          language combined<br>
          with a straightforward standard library is a foundation that
          students can<br>
          comfortably learn on.  Choosing Java gives educators many
          degrees of freedom:<br>
          they can situate students in `jshell` or Notepad or a
          full-fledged IDE; they can<br>
          teach imperative, object-oriented, functional, or hybrid
          programming styles; and<br>
          they can easily find libraries to interact with external data
          and services.  <br>
          <br>
          No language is perfect, and one of the most common complaints
          about Java is that<br>
          it is "too verbose" or has "too much ceremony."  And
          unfortunately, Java imposes<br>
          its heaviest ceremony on those first learning the language,
          who need and<br>
          appreciate it the least.  The declaration of a class and the
          incantation of<br>
          `public static void main` is pure mystery to a beginning
          programmer.  While<br>
          these incantations have principled origins and serve a useful
          organizing purpose<br>
          in larger programs, they have the effect of placing obstacles
          in the path of<br>
          _becoming_ Java programmers. Educators constantly remind us of
          the litany of<br>
          complexity that students have to confront on Day 1 of class --
          when they really<br>
          just want to write their first program.  <br>
          <br>
          As an amusing demonstration of this, in her JavaOne keynote
          appearance in 2019,<br>
          [Aimee Lucido](<a class="moz-txt-link-freetext" href="https://www.youtube.com/watch?v=BkPPFiXUwYk" moz-do-not-send="true">https://www.youtube.com/watch?v=BkPPFiXUwYk</a>)
          talked about when<br>
          she learned to program in Java, and how her teacher performed
          a rap song<br>
          to help students memorize `"public static void main"`.  Our
          hats are off to<br>
          creative educators everywhere for this kind of dedication, but
          teachers<br>
          shouldn't have to do this.<br>
          <br>
          Of course, advanced programmers complain about ceremony too. 
          We will never be<br>
          able to satisfy programmers' insatiable appetite for typing
          fewer keystrokes,<br>
          and we shouldn't try, because the goal of programming is to
          write programs that<br>
          are easy to read and are clearly correct, not programs that
          were easy to type.<br>
          But we can try to better align the ceremony commensurate with
          the value it<br>
          brings to a program -- and let simple programs be expressed
          more simply.  <br>
          <br>
          ## Concept overload<br>
          <br>
          The classic "Hello World" program looks like this in Java:<br>
          <br>
          ```<br>
          public class HelloWorld { <br>
              public static void main(String[] args) { <br>
                  System.out.println("Hello World");<br>
              }<br>
          }<br>
          ```<br>
          <br>
          It may only be five lines, but those lines are packed with
          concepts that are<br>
          challenging to absorb without already having some programming
          experience and<br>
          familiarity with object orientation. Let's break down the
          concepts a student<br>
          confronts when writing their first Java program:<br>
          <br>
            - **public** (on the class).  The `public` accessibility
          level is relevant<br>
              only when there is going to be cross-package access; in a
          simple "Hello<br>
              World" program, there is only one class, which lives in
          the unnamed package.<br>
              They haven't even written a one-line program yet; the
          notion of access<br>
              control -- keeping parts of a program from accessing other
          parts of it -- is<br>
              still way in their future.<br>
          <br>
            - **class**.  Our student hasn't set out to write a _class_,
          or model a<br>
              complex system with objects; they want to write a
          _program_.  In Java, a<br>
              program is just a `main` method in some class, but at this
          point our student<br>
              still has no idea what a class is or why they want one.<br>
          <br>
            - **Methods**.  Methods are of course a key concept in Java,
          but the mechanics<br>
              of methods -- parameters, return types, and invocation --
          are still<br>
              unfamiliar, and the `main` method is invoked magically
          from the `java`<br>
              launcher rather than from explicit code.  <br>
          <br>
            - **public** (again).  Like the class, the `main` method has
          to be public, but<br>
              again this is only relevant when programs are large enough
          to require<br>
              packages to organize them.  <br>
          <br>
            - **static**.  The `main` method has to be static, and at
          this point, students<br>
              have no context for understanding what a static method is
          or why they want<br>
              one.  Worse, the early exposure to `static` methods will
          turn out to be a<br>
              bad habit that must be later unlearned.  Worse still, the
          fact that the<br>
              `main` method is `static` creates a seam between `main`
          and other methods;<br>
              either they must become `static` too, or the `main` method
          must trampoline<br>
              to some sort of "instance main" (more ceremony!)  And if
          we get this wrong,<br>
              we get the dreaded and mystifying `"cannot be referenced
          from a static<br>
              context"` error.<br>
          <br>
            - **main**.  The name `main` has special meaning in a Java
          program, indicating<br>
              the starting point of a program, but this specialness
          hides behind being an<br>
              ordinary method name.  This may contribute to the sense of
          "so many magic<br>
              incantations."<br>
          <br>
            - **String[]**.  The parameter to `main` is an array of
          strings, which are the<br>
              arguments that the `java` launcher collected from the
          command line.  But our<br>
              first program -- likely our first dozen -- will not use
          command-line<br>
              parameters. Requiring the `String[]` parameter is, at this
          point, a mistake<br>
              waiting to happen, and it will be a long time until this
          parameter makes<br>
              sense.  Worse, educators may be tempted to explain arrays
          at this point,<br>
              which further increases the time-to-first-program.<br>
          <br>
            - **System.out.println**.  If you look closely at this
          incantation, each<br>
              element in the chain is a different thing -- `System` is a
          class (what's a<br>
              class again?), `out` is a static field (what's a field?),
          and `println` is<br>
              an instance method.  The only part the student cares about
          right now is<br>
              `println`; the rest of it is an incantation that they do
          not yet understand<br>
              in order to get at the behavior they want.<br>
          <br>
          That's a lot to explain to a student on the first day of
          class.  There's a good<br>
          chance that by now, class is over and we haven't written any
          programs yet, or<br>
          the teacher has said "don't worry what this means, you'll
          understand it later"<br>
          six or eight times.  Not only is this a lot of _syntactic_
          things to absorb, but<br>
          each of those things appeals to a different concept (class,
          method, package,<br>
          return value, parameter, array, static, public, etc) that the
          student doesn't<br>
          have a framework for understanding yet.  Each of these will
          have an important<br>
          role to play in larger programs, but so far, they only
          contribute to "wow,<br>
          programming is complicated."  <br>
          <br>
          It won't be practical (or even desirable) to get _all_ of
          these concepts out of<br>
          the student's face on day 1, but we can do a lot -- and focus
          on the ones that<br>
          do the most to help beginners understand how programs are
          constructed.<br>
          <br>
          ## Goal: a smooth on-ramp<br>
          <br>
          As much as programmers like to rant about ceremony, the real
          goal here is not<br>
          mere ceremony reduction, but providing a graceful _on ramp_ to
          Java programming.<br>
          This on-ramp should be helpful to beginning programmers by
          requiring only those<br>
          concepts that a simple program needs.  <br>
          <br>
          Not only should an on-ramp have a gradual slope and offer
          enough acceleration<br>
          distance to get onto the highway at the right speed, but its
          direction must<br>
          align with that of the highway.  When a programmer is ready to
          learn about more<br>
          advanced concepts, they should not have to discard what
          they've already learned,<br>
          but instead easily see how the simple programs they've already
          written<br>
          generalize to more complicated ones, and both the syntatic and
          conceptual<br>
          transformation from "simple" to "full blown" program should be
          straightforward<br>
          and unintrusive.  It is a definite non-goal to create a
          "simplified dialect of<br>
          Java for students".<br>
          <br>
          We identify three simplifications that should aid both
          educators and students in<br>
          navigating the on-ramp to Java, as well as being generally
          useful to simple<br>
          programs beyond the classroom as well:<br>
          <br>
           - A more tolerant launch protocol<br>
           - Unnamed classes<br>
           - Predefined static imports for the most critical methods and
          fields<br>
          <br>
          ## A more tolerant launch protocol<br>
          <br>
          The Java Language Specification has relatively little to say
          about how Java<br>
          "programs" get launched, other than saying that there is some
          way to indicate<br>
          which class is the initial class of a program (JLS 12.1.1) and
          that a public<br>
          static method called `main` whose sole argument is of type
          `String[]` and whose<br>
          return is `void` constitutes the entry point of the indicated
          class.  <br>
          <br>
          We can eliminate much of the concept overload simply by
          relaxing the<br>
          interactions between a Java program and the `java` launcher:<br>
          <br>
           - 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>
          <br>
           - 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>
          <br>
           - 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>
          <br>
          This small set of changes to the launch protocol strikes out
          five of the bullet<br>
          points in the above list of concepts: public (twice), static,
          method parameters,<br>
          and `String[]`.  <br>
          <br>
          At this point, our Hello World program is now:<br>
          <br>
          ```<br>
          class HelloWorld { <br>
              void main() { <br>
                  System.out.println("Hello World");<br>
              }<br>
          }<br>
          ```<br>
          <br>
          It's not any shorter by line count, but we've removed a lot of
          "horizontal<br>
          noise" along with a number of concepts.  Students and
          educators will appreciate<br>
          it, but advanced programmers are unlikely to be in any hurry
          to make these<br>
          implicit elements explicit either.  <br>
          <br>
          Additionally, the notion of an "instance main" has value well
          beyond the first<br>
          day.  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.  Formalizing<br>
          the "instance main" protocol reduces a layer of boilerplate in
          these cases, and<br>
          defers the point at which we have to explain what instance
          creation is -- and<br>
          what `static` is.  (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>
          <br>
          ## Unnamed classes<br>
          <br>
          In a simple program, the `class` declaration often doesn't
          help either, because<br>
          other classes (if there are any) are not going to reference it
          by name, and we<br>
          don't extend a superclass or implement any interfaces.  If we
          say an "unnamed<br>
          class" consists of member declarations without a class header,
          then our Hello<br>
          World program becomes:<br>
          <br>
          ```<br>
          void main() { <br>
              System.out.println("Hello World");<br>
          }<br>
          ```<br>
          <br>
          Such source files can still have fields, methods, and even
          nested classes, so<br>
          that as a program evolves from a few statements to needing
          some ancillary state<br>
          or helper methods, these can be factored out of the `main`
          method while still<br>
          not yet requiring a full class declaration:<br>
          <br>
          ```<br>
          String greeting() { return "Hello World"; }<br>
          <br>
          void main() {<br>
              System.out.println(greeting());<br>
          }<br>
          ```<br>
          <br>
          This is where treating `main` as an instance method really
          shines; the user has<br>
          just declared two methods, and they can freely call each
          other.  Students need<br>
          not confront the confusing distinction between instance and
          static methods yet;<br>
          indeed, if not forced to confront static members on day 1, it
          might be a while<br>
          before they do have to learn this distinction.  The fact that
          there is a<br>
          receiver lurking in the background will come in handy later,
          but right now is<br>
          not bothering anybody.<br>
          <br>
          [JEP 330](<a class="moz-txt-link-freetext" href="https://openjdk.org/jeps/330" moz-do-not-send="true">https://openjdk.org/jeps/330</a>)
          allows single-file programs to be<br>
          launched directly without compilation; this streamlined
          launcher pairs well with<br>
          unnamed classes. <br>
          <br>
          ## Predefined static imports<br>
          <br>
          The most important classes, such as `String` and `Integer`,
          live in the<br>
          `java.lang` package, which is automatically on-demand imported
          into all<br>
          compilation units; this is why we do not have to `import
          java.lang.String` in<br>
          every class.  Static imports were not added until Java 5, but
          no corresponding<br>
          facility for automatic on-demand import of common behavior was
          added at that<br>
          time.  Most programs, however, will want to do console IO, and
          Java forces us to<br>
          do this in a roundabout way -- through the static `System.out`
          and `System.in`<br>
          fields.  Basic console input and output is a reasonable
          candidate for<br>
          auto-static import, as one or both are needed by most simple
          programs.  While<br>
          these are currently instance methods accessed through static
          fields, we can<br>
          easily create static methods for `println` and `readln` which
          are suitable for<br>
          static import, and automatically import them.  At which point
          our first program<br>
          is now down to:<br>
          <br>
          ```<br>
          void main() {<br>
              println("Hello World");<br>
          }<br>
          ```<br>
          <br>
          ## Putting this all together<br>
          <br>
          We've discussed several simplifications:<br>
          <br>
           - Update the launcher protocol to make public, static, and
          arguments optional<br>
             for main methods, and for main methods to be instance
          methods (when a<br>
             no-argument constructor is available); <br>
           - Make the class wrapper for "main classes" optional (unnamed
          classes);<br>
           - Automatically static import methods like `println`<br>
          <br>
          which together whittle our long list of day-1 concepts down
          considerably.  While<br>
          this is still not as minimal as the minimal Python or Ruby
          program -- statements<br>
          must still live in a method -- the goal here is not to win at
          "code golf".  The<br>
          goal is to ensure that concepts not needed by simple programs
          need not appear in<br>
          those programs, while at the same time not encouraging habits
          that have to be<br>
          unlearned as programs scale up. <br>
          <br>
          Each of these simplifications is individually small and
          unintrusive, and each is<br>
          independent of the others.  And each embodies a simple
          transformation that the<br>
          author can easily manually reverse when it makes sense to do
          so: elided<br>
          modifiers and `main` arguments can be added back, the class
          wrapper can be added<br>
          back when the affordances of classes are needed (supertypes,
          constructors), and<br>
          the full qualifier of static-import can be added back.  And
          these reversals are<br>
          independent of one another; they can done in any combination
          or any order.<br>
          <br>
          This seems to meet the requirements of our on-ramp; we've
          eliminated most of the<br>
          day-1 ceremony elements without introducing new concepts that
          need to be<br>
          unlearned. The remaining concepts -- a method is a container
          for statements, and<br>
          a program is a Java source file with a `main` method -- are
          easily understood in<br>
          relation to their fully specified counterparts.  <br>
          <br>
          ## Alternatives<br>
          <br>
          Obviously, we've lived with the status quo for 25+ years, so
          we could continue<br>
          to do so.  There were other alternatives explored as well;
          ultimately, each of<br>
          these fell afoul of one of our goals.<br>
          <br>
          ### Can't we go further?<br>
          <br>
          Fans of "code golf" -- of which there are many -- are surely
          right now trying to<br>
          figure out how to eliminate the last little bit, the `main`
          method, and allow<br>
          statements to exist at the top-level of a program.  We
          deliberately stopped<br>
          short of this because it offers little value beyond the first
          few minutes, and<br>
          even that small value quickly becomes something that needs to
          be unlearned.  <br>
          <br>
          The fundamental problem behind allowing such "loose"
          statements is that<br>
          variables can be declared inside both classes (fields) and
          methods (local<br>
          variables), and they share the same syntactic production but
          not the same<br>
          semantics.  So it is unclear (to both compilers and humans)
          whether a "loose"<br>
          variable would be a local or a field.  If we tried to adopt
          some sort of simple<br>
          heuristic to collapse this ambiguity (e.g., whether it
          precedes or follows the<br>
          first statement), that may satisfy the compiler, but now
          simple refactorings<br>
          might subtly change the meaning of the program, and we'd be
          replacing the<br>
          explicit syntactic overhead of `void main()` with an invisible
          "line" in the<br>
          program that subtly affects semantics, and a new subtle rule
          about the meaning<br>
          of variable declarations that applies only to unnamed
          classes.  This doesn't<br>
          help students, nor is this particularly helpful for all but
          the most trivial<br>
          programs.  It quickly becomes a crutch to be discarded and
          unlearned, which<br>
          falls afoul of our "on ramp" goals.  Of all the concepts on
          our list, "methods"<br>
          and "a program is specified by a main method" seem the ones
          that are most worth<br>
          asking students to learn early.<br>
          <br>
          ### Why not "just" use `jshell`?  <br>
          <br>
          While JShell is a great interactive tool, leaning too heavily
          on it as an onramp<br>
          would fall afoul of our goals.  A JShell session is not a
          program, but a<br>
          sequence of code snippets.  When we type declarations into
          `jshell`, they are<br>
          viewed as implicitly static members of some unspecified class,
          with<br>
          accessibility is ignored completely, and statements execute in
          a context where<br>
          all previous declarations are in scope.  This is convenient
          for experimentation<br>
          -- the primary goal of `jshell` -- but not such a great mental
          model for<br>
          learning to write Java programs.  Transforming a batch of
          working declarations<br>
          in `jshell` to a real Java program would not be sufficiently
          simple or<br>
          unintrusive, and would lead to a non-idiomatic style of code,
          because the<br>
          straightforward translation would have us redeclaring each
          method, class, and<br>
          variable declaration as `static`.  Further, this is probably
          not the direction<br>
          we want to go when we scale up from a handful of statements
          and declarations to<br>
          a simple class -- we probably want to start using classes as
          classes, not just<br>
          as containers for static members. JShell is a great tool for
          exploration and<br>
          debugging, and we expect many educators will continue to
          incorporate it into<br>
          their curriculum, but is not the on-ramp programming model we
          are looking for.  <br>
          <br>
          ### What about "always local"?<br>
          <br>
          One of the main tensions that `main` introduces is that most
          class members are<br>
          not `static`, but the `main` method is -- and that forces
          programmers to<br>
          confront the seam between static and non-static members. 
          JShell answers this<br>
          with "make everything static". <br>
          <br>
          Another approach would be to "make everything local" -- treat
          a simple program<br>
          as being the "unwrapped" body of an implicit main method.  We
          already allow<br>
          variables and classes to be declared local to a method.  We
          could add local<br>
          methods (a useful feature in its own right) and relax some of
          the asymmetries<br>
          around nesting (again, an attractive cleanup), and then treat
          a mix of<br>
          declarations and statements without a class wrapper as the
          body of an invisible<br>
          `main` method. This seems an attractive model as well -- at
          first.<br>
          <br>
          While the syntactic overhead of converting back to full-blown
          classes -- wrap<br>
          the whole thing in a `main` method and a `class` declaration
          -- is far less<br>
          intrusive than the transformation inherent in `jshell`, this
          is still not an<br>
          ideal on-ramp.  Local variables interact with local classes
          (and methods, when<br>
          we have them) in a very different way than instance fields do
          with instance<br>
          methods and inner classes: their scopes are different (no
          forward references),<br>
          their initialization rules are different, and captured local
          variables must be<br>
          effectively final.  This is a subtly different programming
          model that would then<br>
          have to be unlearned when scaling up to full classes. Further,
          the result of<br>
          this wrapping -- where everything is local to the main method
          -- is also not<br>
          "idiomatic Java".  So while local methods may be an attractive
          feature, they are<br>
          similarly not the on-ramp we are looking for.<br>
          <br>
          <br>
        </font></font> </blockquote>
    <br>
  </body>
</html>