[HN Gopher] JEP 445: Flexible Main Methods and Anonymous Main Cl...
       ___________________________________________________________________
        
       JEP 445: Flexible Main Methods and Anonymous Main Classes (Preview)
        
       Author : mfiguiere
       Score  : 44 points
       Date   : 2023-04-10 17:41 UTC (5 hours ago)
        
 (HTM) web link (openjdk.org)
 (TXT) w3m dump (openjdk.org)
        
       | hyperpape wrote:
       | Question that just now occurs to me: what if you have the follow
       | class and invoke it? (typing without an IDE, forgive any
       | compilation errors). I can imagine answers, but I'm not sure if
       | the JEP explains which one will happen (genuinely unsure, I
       | could've easily missed it).
       | 
       | public class Foo {                   int x;              public
       | Foo(int x) {             this.x = x;         }
       | void main() {              System.out.println(x);         }     }
        
         | pron wrote:
         | The JEP says:
         | 
         | > If a launched class has no static main method but has a non-
         | private zero-parameter constructor ... and a non-private
         | instance main method, then construct an instance of the
         | class... [and] invoke the instance main method
         | 
         | Your class doesn't have a zero-parameter constructor nor a
         | suitable static main, so launching it as a program will fail
         | (as it would today).
        
       | johnfn wrote:
       | Pretty nice! Makes me wonder why they didn't take the final step
       | and say that anything not inside `void main()` gets bundled up
       | into an implicit function run first.
        
         | djur wrote:
         | It's addressed near the end:
         | 
         | > Eliminating the main method altogether may seem like the
         | natural next step, but it would work against the goal of
         | gracefully evolving a first Java program to a larger one and
         | would impose some non-obvious restrictions (see below):
         | 
         | The "see below" boils down to there being a number of
         | differences between how class-level and method-level code units
         | (fields vs. variables) work, and blurring the line there isn't
         | worth the minor additional effort of writing a main() method.
        
       | specialist wrote:
       | Love it.
       | 
       | Don't forget to support shebang. So we can finally use Java as a
       | system scripting language.
       | 
       | Maybe something like:                   #!/usr/bin/env java
       | 
       | And maybe also allow specifying the runtime version:
       | #!/usr/bin/env java-12.0.*
        
         | carimura wrote:
         | Like this? https://dev.java/learn/single-file-program/
        
       | mfiguiere wrote:
       | The timeline of its promotion from draft status along with
       | several mentions of JDK 21 in the provided examples make it
       | likely to ship with JDK 21 in September.
        
         | kasperni wrote:
         | As a preview feature
        
       | yarg wrote:
       | All I can think coming away from this is:
       | 
       | This still seems pretty useless, It'd be nice if java could allow
       | for static interface methods.                   interface Program
       | {             static void main(String...args);         }
       | 
       | And then I digressed - heavily.
       | 
       | There have been several times when I've wanted static methods
       | that apply to the specific class - although many of the
       | situations could be shoehorned into a constructor, it's not the
       | best.
       | 
       | You'd also want something like a 'This' meta-class keyword.
       | interface Foo extends Comparable<This> {                  static
       | This(A argA, B argB);                  static This
       | difference(This v0, This v1);                  static int
       | compare(This v0, This v1);                  default int
       | compareTo(This other){                 return compare(v0, v1);
       | }              }              /*             I want to return an
       | instance of my class' own type (defined in a subclass an so
       | unknown),             so I pass every implementation itself as
       | its own generic parameter.         */              interface
       | Why<W extends Why<W>> implements Comparable<W>{             W
       | someManipulation();           }              class Foo implements
       | Why<Foo> {             @Override             Foo
       | someManipulation(){                 ....             }         }
       | 
       | To be honest, I think I reacted to how robust this does not feel.
       | 
       | It also blurs the line between static and instance
       | syntax/functionality in a way that does not seem useful - and
       | given that this is intended to reduce barriers to entry, is quite
       | probably harmfully confusing.
        
         | yarg wrote:
         | A better example of what I'm thinking:
         | interface Number {             static This sum(This v0, This
         | v1);             static This difference(This v0, This v1);
         | static This product(This v0, This v1);             static This
         | quotient(This v0, This v1);         }              void <N
         | extends Number> doThings(N v0, N v1){             N sum =
         | N.sum(v0, v1);         }
        
       | tpoacher wrote:
       | My 2C/ is that this will probably do more to confuse than to
       | enlighten students.
       | 
       | Getting your "first" program off the ground quickly is good, but
       | only if it doesn't cripple your understanding of what's going on
       | for months later.
       | 
       | For me the main thing that confuses the crap out of students is
       | how people who introduce java tend to take "shortcuts" and bundle
       | all functionality under the sun into a single class, which then
       | also has a main method at the end. Presumably this is done so
       | that everything is a single file, or can fit in a single
       | presentation slide. But then suddenly your main looks like it's
       | calling its container class to make objects of "itself" that
       | contain new "mains", at which point your student has lost the
       | plot completely.
       | 
       | The simplest thing to keep things clean and self explanatory is
       | to separate everything that isn't "main-related" into its own
       | class (preferably another file if public), and then keep a nice
       | clean public class called "Main" which contains 'only' the main
       | method. Then you get to explain nicely how public classes have
       | their own files, and if you attempt to run this class from the
       | terminal, java will look for the 'main' function, and how this
       | therefore needs to be public, static because you're running it
       | straight from the class, void because you don't depend on it
       | returning a value (which also makes for a nice intermission on
       | how c returns status as an int, but java has a special mechanism
       | instead).
       | 
       | I do agree with the end of the JEP though; if you want to teach
       | simple snippets like System.out.println, jshell is a nice way to
       | do this, if you want to delay talking about classes and their
       | methods.
        
       | WhereIsTheTruth wrote:
       | Kotlin and the likes proved them wrong
       | 
       | Glad to see them evolving faster as a result
        
       | clhodapp wrote:
       | I'd love to see them follow with full-blown package-level methods
       | and fields at some point (as alluded to in the alternatives) but
       | this seems like a great minimal change to address a real pain
       | point with learning to code in Java.
        
       | hyperpape wrote:
       | The section on how the main method will be resolved is a bit
       | painful. I can't see a way around it that doesn't do nasty things
       | for composability and/or backwards compatibility, but it does
       | give me pause. Any situation where you have to ask "which main
       | method in this class will be executed?" is quite bad.
        
         | pgwhalen wrote:
         | As much as it's a crutch in programming language design to say
         | "we don't have to worry too much about the lack of ergonomics
         | in this case, it would be such bad code if this edge case gets
         | run into in the first place," this seems like one of those
         | situations.
         | 
         | Another point: IDEs will be able to tell you which main method
         | will get chosen, which should eliminate at least some
         | uncertainty.
        
         | pron wrote:
         | Which is why, as part of designing this feature, we ran a
         | corpus search to see what portion of classes with a main method
         | have another main that would be a candidate entry point under
         | this JEP. It was negligible. Additionally, we'll give a linter
         | warning if there's more than one candidate.
        
       | java-man wrote:
       | I feel like this is introducing a change for the sake of change,
       | solving a problem which does not exist. The price of this change
       | is very real: adding complexity and bugs to all the tools, IDEs,
       | code analyzers and the like.
       | 
       | There is negative net benefit to pretty much everyone involved,
       | and for what?
        
         | justin_oaks wrote:
         | I do wonder how much benefit will be gained from this. Is the
         | main method really causing beginners that many problems?
         | 
         | I'd say beginners are much more likely to trip over other
         | problems with the language like using == with String instances,
         | the differences between primitives and objects (e.g. copy-by-
         | value vs copy-by-reference, no methods on a primitive, etc.),
         | or the unending problems with null.
         | 
         | Of course, those may never be resolved, and so we'll have to
         | change something that doesn't really matter instead.
        
           | crummy wrote:
           | Not sure if you're being sarcastic but the solution to some
           | of those things is on the horizon (e.g. null awareness).
           | Seems like a lot of work is necessary to get there though.
        
         | Pet_Ant wrote:
         | That is literally what is addressed by the first section of the
         | document. Both in "Summary" and in "Goals"
         | 
         | > Far from using a separate dialect of Java, students can write
         | streamlined declarations for single-class programs and then
         | seamlessly expand their programs to use more advanced features
         | as their skills grow.
         | 
         | I remember when I started with Java 20 years we had a special
         | IDE (BlueJ maybe? DrJava?) that wrapped the main class so that
         | <code>System.out.println("Hello world");</code> was a complete
         | program.
         | 
         | So that is clearly
         | 
         | > Do not introduce a separate beginner's dialect of Java.
         | 
         | Perhaps this is in response to Python growing as an initial
         | programming language (IMHO wrongly because types are
         | fundamental to thinking about programming).
         | 
         | They also mention:
         | 
         | > Reduce the ceremony of writing simple programs such as
         | scripts and command-line utilities.
         | 
         | You can question the merits or trade-offs, but it's very
         | clearly spelled out.
         | 
         | > Reduce the ceremony of writing simple programs such as
         | scripts and command-line utilities.
        
           | java-man wrote:
           | Is this really what students struggle with?
           | 
           | I think it is important to be able to determine the root
           | cause of a problem first. Do students find difficult to write
           | "public static void main(String[] args)" or do they find
           | difficulty understanding the concepts of a public method, a
           | static method, a void method? Perhaps then we should focus on
           | teaching these concepts, which are essential to java, first,
           | instead of undermining the core of the language and the
           | platform.
           | 
           | Neither "goals" nor "summary" can explain away why this can
           | solve the problem this JEP purports to solve.
           | 
           | This is my opinion, of course.
        
             | OkayPhysicist wrote:
             | The problem is when you sit down to teach the beginner, all
             | the boilerplate clutter forces you to either A) teach them
             | the magic incantation to be unquestionably written before
             | they start writing any code, or B) you explain everything
             | before getting into any real programming.
             | 
             | Both suck. In the first case, students are torn away from
             | the mode of thinking that programming thrives in: that
             | everything is made up of simple, understandable pieces,
             | that can be built up into complex solutions. It ends up
             | serving as a trap for the very kind of inquisitive student
             | that is equipped to succeed in programming. In the second
             | case, everyone's bored to tears, and you can be assured
             | that your entire class will be hopelessly lost before they
             | write their first line of code. It's a bad time all around.
             | 
             | Basically, programming wants to be built up with the
             | following concepts, in order:
             | 
             | 1. Algorithmic Thinking (solutions can be representing as a
             | series of simple steps)
             | 
             | 2. Structured Syntax (these steps can be represented as
             | structured text)
             | 
             | 3. Symbolic Reasoning (types, variables, arrays)
             | 
             | 4. Control Flow (loops, conditionals)
             | 
             | 5. Functions
             | 
             | 6. Higher Structures (classes, objects, etc)
             | 
             | Python, IMO, is pretty good pedagogical tool in this regard
             | print("Hello World")
             | 
             | "We want our computer to display to us (or 'print' in
             | software terms) the phrase 'Hello World'. Python provides
             | us with a built-in way to do so: the "print" function. In
             | the majority of programming languages, we express a call to
             | a function as a command, followed by its inputs (or
             | 'arguments') contained within parentheses. As our one and
             | only argument, we provide what we want printed, in this
             | case the text "Hello World". By wrapping this text in
             | quotes, we can tell the language that we intend this text
             | to be interpreted as a chunk of literal text, called a
             | 'String' rather than as a variable or other symbol for the
             | language."
             | 
             | In contrast, explaining everything going on in the
             | equivalent Java                   public class MyFirstClass
             | {             public static void main(String[] args){
             | System.out.println("Hello World");             }         }
             | 
             | would take more text than I'm willing to hammer into a HN
             | comment, but to be explained to a complete beginner would
             | likely involve skipping, but promising to explain later:
             | classes, functions, "public", "static", "void", command
             | line arguments, and the uniquely weird "System.out",
             | followed by a similar explanation to the Python example,
             | with the added "we end each step with a semicolon".
        
               | java-man wrote:
               | Thank you for a detailed explanation!
               | 
               | Please see my response to @pgwhalen. In short, the
               | problem has, I think, a much simpler solution.
               | 
               | What I really dislike about this JEP is not only that it
               | tries to solve the educational problem in a worst
               | possible manner (my opinion), but it also risks creating
               | a generation of students who don't really understand the
               | fundamental concepts that allow us to write reliable
               | code.
               | 
               | Perhaps we need to start teaching basic programming with
               | BASIC instead, and graduate to a more complicated
               | platform once the basic concepts have been understood.
        
               | OkayPhysicist wrote:
               | My personal opinion on it is that Java's simply a bad
               | first language, and over-taught in schools. It has a lot
               | of language-specific baggage that it thrusts upon you
               | immediately on first use. My preferred first (university-
               | level) language is Racket, because it's got incredibly
               | simple syntax as a LISP, it's radically batteries-
               | included giving a good sandbox to play in, and segues
               | into CS-theory type stuff pretty damn well. It also has
               | the added bonus of minimizing the impact on the subset of
               | the class with non-trivial programming experience, who
               | otherwise can easily get bored hearing stuff they know
               | already, stop paying attention because they assume they
               | know everything already, and then wash out when the real
               | CS-heavy stuff hits.
               | 
               | But a lot of "universities" treat their "CS" programs as
               | glorified trade schools, and want to focus exclusively on
               | industry-applicable languages, and land on Java because
               | Oracle had a great outreach program. Like it or not, many
               | students will be starting their programming journey in
               | Java, and not fucking it up is probably a good idea.
               | 
               | My approach would have been pretty similar to their
               | listed alternative under "Interpret code units as static
               | members", but that probably comes down to differences
               | over the importance of Object-Oriented principals in
               | beginner programming pedagogy.
               | 
               | Barring that, this proposal really isn't bad. It doesn't
               | break existing code, it does its job well enough. I would
               | have liked there to be support for inline subclasses that
               | can be called from within the same anonymous class
               | environment, but I can see how that would create
               | ambiguity with existing code.
        
             | pron wrote:
             | > Perhaps then we should focus on teaching these concepts,
             | which are essential to java, first.
             | 
             | As the JEP explains, this change does make the concepts of
             | classes and access modifiers easier to teach by allowing
             | the teacher to postpone their introduction to a point in
             | time when they're actually useful and can be understood.
             | Access control, static, and class declarations are only
             | meaningful once you have _other_ classes and /or objects
             | interacting with your code. We don't want to force teachers
             | to teach programming in the large early because many of
             | them told us they don't do that anyway.
             | 
             | > instead of undermining the core of the language and the
             | platform
             | 
             | The syntax and concepts of anonymous classes are unchanged.
             | Providing an unnamed class, implicitly, when a class isn't
             | needed is consistent with how we already provide an unnamed
             | package and an unnamed module implicitly when they're not
             | needed.
        
             | pgwhalen wrote:
             | It sounds like you haven't taught or taken an intro to
             | programming course using Java before.
             | 
             | In that situation, instructors might spend weeks trying to
             | get their students to understand variables or control flow
             | concepts. Visibility may be a core concern for you, as a
             | (presumably) professional Java programmer, but it's not at
             | all to programming novices.
        
               | java-man wrote:
               | This particular problem, in my opinion, has a much
               | simpler solution: a special educational environment. A
               | sort of mini-IDE where two things happen:
               | 
               | 1. code written by a student gets inserted into a top-
               | level class's main() method (has to be smart enough to
               | deal with imports, inner classes etc.)
               | 
               | 2. the top level class might declar certain utility
               | functions such as print() instead of
               | System.out.println(), and possibly others.
               | 
               | Bingo. No need to mess with something that works just
               | fine for 99.99% of the professional users.
               | 
               | edit, in response to @crummy (as we reached the maximum
               | depth it seems):
               | 
               | Some people commented that it might be beneficial to
               | delay introduction of more complex concepts until the
               | basic ones are digested. So hiding the class/main method
               | would help with that (similar to jshell, I might add).
               | And keep in mid this is an IDE and not java-lite.
        
               | crummy wrote:
               | In your other comment you said:
               | 
               | > What I really dislike about this JEP is not only that
               | it tries to solve the educational problem in a worst
               | possible manner (my opinion), but it also risks creating
               | a generation of students who don't really understand the
               | fundamental concepts that allow us to write reliable
               | code.
               | 
               | How would your special IDE/forked Java-lite prevent
               | creating a generation of students who don't really
               | understand the fundamental concepts that allow us to
               | write reliable code?
        
               | djur wrote:
               | Such an environment already exists, and the JEP rejects
               | it as an option:
               | 
               | > Evolving a batch of working declarations in JShell into
               | a real Java program leads to a non-idiomatic style of
               | code because it declares each method, class, and variable
               | as static... it is not the on-ramp programming model we
               | are looking for.
        
         | easton wrote:
         | Why would this cause extreme problems for Java where it didn't
         | for C# doing the same thing a few years ago? I'm honestly
         | asking not having done Java in a few years, as I remember they
         | both had this "you gotta put all the code in classes" problem.
        
         | ht_th wrote:
         | In my experience teaching introductory programming with Java,
         | the problem is very real. For beginning programmers, making
         | sense of the first Java program(s) results too often in
         | misunderstanding of all sorts of concepts.
         | 
         | Of course, you can tell students to ignore most of the code
         | until later in the course when they'll learn all about it, but
         | that doesn't work. They'll make sense of the code within their
         | limited understanding of programming and frames of reference.
         | They'll build local theories of how and why these programming
         | elements, like "static", "class", "main", "String[]" etc. fit
         | together, how they relate to error messages they get when their
         | programs don't compile or don't work.
         | 
         | Then, when they do reach the place in the course when they're
         | to learn all about these concepts, they have to reconcile their
         | own local theories with the material at hand to create a more
         | thorough and evolved understanding of the concept. That's often
         | not an easy process. In many introductory programming courses,
         | there's not much time for reflection. As a result, their
         | evolving understanding is likely closer to their initial
         | understanding instead of the ones we aim at as teachers.
         | 
         | What's not helping here is that as experienced programmers who
         | have developed a deep understanding of these concepts to
         | understand novice's point-of-view and their struggles with the
         | material.
         | 
         | Learning and teaching is hard!
        
           | justin_oaks wrote:
           | Thanks for explaining the problem. Do you think the proposed
           | changes will help significantly and will be worth the
           | trouble?
        
           | [deleted]
        
           | smarks wrote:
           | Thanks for raising this issue. What you describe as "local
           | theories" (I'd say "mental model" but I think we're talking
           | about the same thing) is quite important. We expect beginners
           | to come up with erroneous models as they're exposed to stuff;
           | revising and even discarding such models is intrinsic to
           | learning. One of the benefits of this JEP is to minimize the
           | opportunities for beginners to create erroneous mental
           | models.
        
         | slaymaker1907 wrote:
         | I've written a ton of Java and I'd find this handy for datetime
         | stuff. Even though I don't use it for my work anymore, I still
         | pull out Java when I need to answer questions like what day is
         | 90 days from now because java.time.* is very well designed.
         | Instead of just using the shell, this makes things a little
         | nicer with less ceremony if I want to do these date
         | calculations in a local file.
        
       ___________________________________________________________________
       (page generated 2023-04-10 23:01 UTC)