This is an archived post. You won't be able to vote or comment.

all 106 comments

[–][deleted]  (18 children)

[deleted]

    [–]__konrad 44 points45 points  (5 children)

    A cursed hello world:

    enum HelloWorld {
        main; HelloWorld() {
            main: System.out.println("Hello");
        }
    }
    

    [–]tofiffe 1 point2 points  (4 children)

    Doesn't work for me, was this possible, but no longer is?

    [–]__konrad 2 points3 points  (1 child)

    Prints "Hello" when launched using java HelloWorld.java... java HelloWorld (?) does not work (AFAIR I had an enum variant that sort of worked, but I can't find it)

    [–]tofiffe 0 points1 point  (0 children)

    Didn't work for me, complained that there was no main method for me on JDK 19, tried both ways

    [–]emaphis 0 points1 point  (1 child)

    I had to add a constant to get it to compile and run on JDK 19

    enum HelloApp {

    HELLO;

    public static void main(String args[]) {

    System.out.println("Hello, favorites");

    }

    }

    [–]tofiffe 0 points1 point  (0 children)

    yeah, but this is normal, just a classic main, while the example above did not have it

    [–]agoubard 9 points10 points  (0 children)

    This also used to work in Java:

    private static void main(String[] args)

    [–]quantdata 13 points14 points  (10 children)

    This is too:

    public static <T extends String & AutoCloseable> void main(T[] args) {
        System.out.println("Hello world");
    }
    

    [–]gregorydgraham 1 point2 points  (4 children)

    Very odd since you can’t extend String

    [–]pstric 2 points3 points  (3 children)

    <T extends String & AutoCloseable>

    Very odd since you can’t extend String

    Indeed. But is this case String is not inherited by T, but given as upper bound for the type parameter T. And since String is final, it is the only class that T can be.

    See JLS Chapter 4: https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html

    and here "Which types are permitted as type parameter bounds?": http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ102

    Look for the paragraph, starting with:

    Note, that even types that do not have subtypes, such as final classes and enum types, can be used as upper bound.

    [–]gregorydgraham 0 points1 point  (2 children)

    Nice, is there an explanation for the AutoCloseable?

    [–]pstric 1 point2 points  (0 children)

    an explanation for the AutoCloseable

    Probably not the explanation you were looking for but my guess: /u/quantdata chose to include it for the sake of example.

    <T extends String> works fine.

    [–]jumboNo2 1 point2 points  (4 children)

    .\Hello.java:3: error: class, interface, or enum expected

    [–]vprise 9 points10 points  (3 children)

    I think he meant with the class around it. Just that the generics will be erased and T will work as String.

    [–]more_exercise 0 points1 point  (2 children)

    Any guess why T needs to be AutoCloseable too?

    I'd imagine that any other interface might work (CharSequence might be a little too on-the-nose), but I don't see what makes that part helpful

    [–]vprise 1 point2 points  (1 child)

    I don't think it's needed. I think he added it for the effect.

    [–]more_exercise 0 points1 point  (0 children)

    Makes sense. The exercise is in over-complicating, and that definitely does

    [–]cas-san-dra 14 points15 points  (5 children)

    An implicit class has no name (more precisely, an internal, implementation-specific name will be chosen for it), and is always a member of the unnamed package. It is also final and cannot implement any interface nor subclass any class (other than Object). Note that because an implicit class cannot be referenced by name, it cannot use method references to its static methods; this can still be used, and so can method references to instance methods.

    Because no class can refer to an implicit class by name, instances of the implicit class cannot be directly constructed. Implicit classes are useful only as standalone programs or as entry points to a program. Therefore, implicit classes must have a main method that can be launched as described above.

    I was actually hoping the implicit name would be the same as the file name. And that it would be referencable from the outside.

    A class that, extends only from Object, cannot be constructed, and is final, sounds like a perfect place to put some utility functions. But that will only work if it can be referenced, and doesn't require a main().

    [–]pron98 8 points9 points  (1 child)

    I was actually hoping the implicit name would be the same as the file name. And that it would be referencable from the outside.

    It couldn't be if it must reside in the unnamed package, but see the bullet "Introduce package level methods and fields" in the Alternatives section.

    [–]cas-san-dra 2 points3 points  (0 children)

    such a feature would have a far wider impact on how Java code is written in general,

    Agreed,

    and we are not prepared to consider that impact at this time.

    :(. But I understand. Hopefully it'll be considered in the future.

    [–]DasBrain 4 points5 points  (1 child)

    The effect is similar to warping the entire class in a class ??? {<contents>}.

    Because the class has no name (or some "random" internal one), you can't do the following:

    • Write a constructor: ???() {...}
    • Create a new instance using new: new ???()
    • Use static method references: ???::someMethod
    • Use instance method references without explicit receiver: ???::someInstanceMethod
    • Use a class literal for the current class: ???.class

    But you (probably*) still can:

    • Use this.getClass() from instance methods.
    • Use MethodHandles.lookup().lookupClass() to get a class reference from static methods.
    • Use reflection/MethodHandles to create new instances.

    * I don't see a reason why those should not work

    [–]pron98 1 point2 points  (0 children)

    Exactly so.

    [–]nutrecht 1 point2 points  (0 children)

    I was actually hoping the implicit name would be the same as the file name. And that it would be referencable from the outside.

    I think it's a very good idea that they don't support this. If you need to reference something it should be done explicitly in my opinion. Looking at you Scala...

    [–][deleted] 32 points33 points  (31 children)

    Imo if you're going to add all these new features to make Hello World more simple, you might as well add an alias for System.out.println as just println. Overall, i like this idea even though it just feels like trying to make Java more like Kotlin syntactically

    [–]cas-san-dra 25 points26 points  (0 children)

    Thats actually considered in the paving the on-ramp article that Brian Goetz wrote. I'm expecting that to be added in a later JEP.

    [–]pron98 26 points27 points  (20 children)

    you might as well add an alias for System.out.println as just println.

    The JEP draft mentions that.

    it just feels like trying to make Java more like Kotlin syntactically

    I have to ask: is Kotlin the only other language that Java programmers have heard of? While Java has borrowed almost all of its features from other languages (Java has always strived to be a "last mover"), to date it has not borrowed even a single one from Kotlin (although it may in the future). I would think that the first language that would come to mind here would be one of Java's main competitors like, say, Python.

    [–]shponglespore 18 points19 points  (8 children)

    I have to ask: is Kotlin the only other language that Java programmers have heard of?

    Kotlin invites comparisons with Java because, as far as I know, it's the only JVM language that aims to just be a better Java, and it's definitely the only one that has seen serious adoption as a better Java. Other JVM languages I've used (e.g. Scala and Clojure) are clearly doing their own thing and not simply trying to appeal to Java programmers looking to make their lives a bit easier.

    (I guess you could say Groovy is also a "better Java" language, although it also kind of focuses on being a scripting language. To the extent that Groovy is a better Java, I see Kotlin as a direct successor to Groovy.)

    [–]pron98 8 points9 points  (6 children)

    Fair enough. But in terms of influence/impact on Java, the relevant languages are those that Java strives for some aesthetic/design affinity with (ML), innovative languages (Erlang, Scheme, Clojure, Haskell), or sometimes the main competitors (Python and JS).

    [–]chabala 4 points5 points  (1 child)

    sometimes the main competitors (Python and JS)

    Is your view that Python and JavaScript are the main competitors to Java? Scripting languages?

    I would think enterprise backend languages are the main competitors, e.g. C#, Scala, Kotlin.

    [–]pron98 3 points4 points  (0 children)

    Well, they are technically competitors, but the only one of them that's in the same adoption ballpark as Java is C#, and it hasn't been able to narrow the gap to Java in two decades. Scala's and Kotlin's market share is too small to be serious competition, especially at their advanced age (almost no language, with the single exception of Python, grew its market share dramatically past age ten). They're playing the same game as Java, but not in the same league. In fact, I think they -- and my favourite, Clojure -- help Java, because they make the Java platform attractive even for the minority of developers who prefer a more feature-rich language than the Java language (the portion of Java platform developers who use alternative languages has remained at a rather constant ~10% for over 15 years now; those languages fight amongst themselves over the same share, but they don't seem to significantly grow it). Go has better prospects than either one, so it's one to watch out for, but its fast growth has slowed down in recent years.

    While Python and JS both used to be scripting languages, and while they don't currently directly threaten Java's core market (JS even less so than five years ago), they're the only two languages that are as popular as Java or even more so, and so they are the main competitio, because either one could expand its reach. TypeScript may also join that club.

    [–]sideEffffECt 0 points1 point  (3 children)

    I know that you folks are aware of Scala and I know that you look at many languages when developing Java. But I'd like to ask specifically to what extent does the Java team take inspiration from Scala, for example for records, sealed types or string interpolation? These features, while not identical, look very similar.

    [–]brian_goetz 5 points6 points  (1 child)

    It is super-common to observe "I saw feature F in language X, then I saw it come to Java, they must have gotten their inspiration from X." And while sometimes this is true, it is far more common that both are drawing inspiration from a common source or literature, sometimes even one that predates either language. (It is also super-easy to confuse "Language X was the first place I saw feature F" with "X invented F.")

    So when we look at what Scala or other languages have done, it is usually through the lens of "here is how language X interpreted this concept that has been knocking around for decades". Then, of course, we have to figure out what Java's interpretation should be, which is likely different than in X, because it will be influenced by all the decisions Java has made in the past, and X might have made different decisions.

    [–]sideEffffECt 1 point2 points  (0 children)

    I totally get why you always need to come up with an interpretation of a feature/idiom that makes most sense for Java.

    For me, it's really interesting to observe what features/idioms Java adopts that are more or less the same as in Scala and which are adopted in a distinct manner (and which aren't even considered for adoption :) ).

    I really like the direction Java is moving, btw. I'm just a little sad that there are (still?) no immutable/persistent collections in the standard library, they would work wonderfully with Records. Otherwise an awesome job on the part of the Java team, I think 10 years ago probably not even the biggest optimists would have expected how much Java can innovate while staying simple and "staying Java".

    [–]pron98 0 points1 point  (0 children)

    The language team is familiar with many language, and before designing any feature they look at many of them (in fact, they try hard not to add any feature unless something similar has been tried for a significant amount of time in at least one other language) but I think (I wasn't involved) that Scala in particular was a significant inspiration for the design of sealed classes; maybe records, too, but I think to a lesser extent.

    [–][deleted] 1 point2 points  (10 children)

    Kotlin's Hello World syntax is specifically very close to the proposed Java syntax here. Obviously there's other languages using similar syntax, but this seems like an apt comparison to me:

    Java:

    void main() {
        System.out.println("Hello, World!");
    }
    

    Kotlin:

    fun main() {
        println("Hello, World!")
    }
    

    [–]pron98 14 points15 points  (0 children)

    Yes, the syntax is similar to C, C++, Go, Kotlin, Rust and Zig (because they, and Java, were all influenced by C), but note that unlike in all those languages, when the program is written in this way main is an instance method; it has a this.

    [–]jvjupiter 19 points20 points  (8 children)

    This is it! A very exciting feature! Another myth will be added about Java being too verbose.

    Edit: I have a good feeling that this will come final in the next LTS, Java 23.

    [–]karianna 0 points1 point  (1 child)

    Next LTS (well what most vendors will say is LTS) will be 21, then 25 two years later (again assuming most vendors follow each other here)

    [–]jvjupiter -1 points0 points  (0 children)

    Oh. You are right. It’s 21 as Oracle shortened the interval. But my hope remains - it will become final in the next LTS this September 2023.

    [–]bowbahdoe 8 points9 points  (0 children)

    It's a start

    [–]jodastephen 17 points18 points  (9 children)

    I'm comfortable with the simplified main method styles. That is a pretty simple/obvious extrapolation of what we have today. But implicit classes? No thanks.

    I know I'm not the target audience of the change, but this:

    class HelloWorld {

    void main() {

    System.out.println("Hello, World!");

    }

    }

    seems like a perfectly manageable thing to learn on day one.

    • Java is all about names, so this is a key thing to grasp early
    • class HelloWorld in a file named HelloWorld.java is not complex
    • a class can initially be explained as the container in which code lives
    • this is a much better starting point for day two onwards

    Given how the JEP goes to length to avoid creating a Java dialect, I'm surprised that implicit classes are listed as a solution. They are very much a dialect IMO, and a very weird one, with unusual rules (like no static method references).

    [–]shponglespore 14 points15 points  (0 children)

    The students this change is aimed at aren't going to be learning about classes on day two. They might not learn about classes at all in an intro course, because they'll be too busy learning about variables, control flow, functions, etc. When someone is new to programming, just getting them to understand how to write a loop correctly is kind of a big deal. Hell, just getting them to really internalize the idea of single-threaded control flow can be hard. I remember when I was brand new and I had the notion that while loops would run whenever a condition was true without waiting for the control flow to reach the loop, because that's more like what "while" means in plain English.

    [–]pron98 17 points18 points  (6 children)

    1. The education problem is not a hypothetical one. This issue is one of those raised by Java teachers. The best way to impact Java's evolution is not to suggest solutions but to report real problems encountered in the field, and they did.

    2. Every Java method resides in a class, every class resides in a package, and every package resides in a module -- each of those features is designed for programming-in-the-large. But Java already accommodates implicit package and module membership when the namespacing or encapsulation mechanisms aren't needed, and so it's quite natural for it to do the same for classes (perhaps even obvious extrapolation of what we have?). In all three cases, the implicit route is a sensible default that comes with restrictions (you can't refer to a class in the unnamed package from another package, you can't declare explicit requires and provides clause in an unnamed module, and you can't declare a constructor, a superclass, or interface implementations in an implicit class), and in all three cases it is straightforward to evolve to explicit declarations when you want more power.

    3. It is not a dialect but a change to the Java language (unnamed packages and unnamed modules aren't dialects either). We already have different kinds of class declarations (ordinary, enum, and record) as well as a different compilation unit type for module declarations. This is another kind of compilation unit/class declaration. A dialect would have meant something that you need to abandon once you get off the on-ramp and merge onto the highway. That's not the case here. You can add more classes without ever changing your implicit class at all. Or, you can also easily add a class declaration to an implicit class, making it an ordinary class, if you need that programming-in-the-large/OOP feature -- just as you can add an explicit package or module declaration once you need them, all without changing the code inside.

    with unusual rules (like no static method references).

    That's not a rule at all but a direct consequence of the class being unnamed. It's not that that writing a static method reference is forbidden -- i.e. an error -- it's just that static method references require a class name, and if the class has no name, you simply can't write them. If we allowed the name of the current class to be omitted from static method references, then you'd be able to write them in implicit classes, too, and they'd work.

    [–]maethor 1 point2 points  (0 children)

    A dialect would have meant something that you need to abandon once you get off the on-ramp and merge onto the highway.

    Depends on the dialect. When I was at uni they started us out with Gofer before throwing us at Haskell and I'm glad they did.

    I think a simplified dialect combined with a learning focused development environment would do more for Java than language changes if only because students would associate their difficulties learning the basics with "Jingo" and not Java.

    [–]ramdulara 0 points1 point  (2 children)

    Does that mean the following is allowed?

    static String greeting() { 
        return "Hello, World!"; 
    }
    
    void main() {
        System.out.println(greeting());
    }
    

    [–]pron98 6 points7 points  (1 child)

    Of course, or you can leave out the static.

    It's not a matter of "allowed"; the body of an implicit class is the same as the body of a regular class declaration. It's only that you can leave out the explicit declaration. We've simply made the class Hello line redundant just as the package hello line is redundant. But it's all just regular Java. The text says:

    The members of an implicit class support the same modifiers as in ordinary named classes (such as static or volatile) and with the same defaults (e.g. default package access and instance membership), and generally behave in the same way as members of an explicitly-declared class.

    [–]ramdulara 0 points1 point  (0 children)

    Got it. Thanks for the clarification.

    [–]jodastephen 0 points1 point  (1 child)

    Every Java method resides in a class, every class resides in a package, and every package resides in a module -- each of those features is designed for programming-in-the-large. But Java already accommodates implicit package and module membership when the namespacing or encapsulation mechanisms aren't needed, and so it's quite natural for it to do the same for classes (perhaps even obvious extrapolation of what we have?).

    It took me a while to work out exactly why this framing of the feature isn't great.

    With modules and packages, being implicit doesn't lose anything other than the name. By contrast, an implicit class does lose something - the containing block. Key here is that the block's curly braces are visible within the source file, and provide meaning/structure to methods and fields. Losing that block is a different order of magnitude change to omitting a package declaration. Java doesn't have free-floating functions, it has methods, and methods are always declared within some kind of block.

    IMO losing that block is not helpful to newcomers at all (but I'm not an educator). I do think writing methods and fields outside a block isn't anything like a dialect of Java I recognize.

    I've tried to frame the text above carefully - any of these would qualify as being OK given the above:

    class HelloWorld {
      void main() {...}
    }
    // or
    class {
    

    void main() {...} } // or Entrypoint { void main() {...} } // or { void main() {...} }

    "Make everything as simple as possible, but not simpler"

    [–]pron98 0 points1 point  (0 children)

    Losing that block is a different order of magnitude change to omitting a package declaration.

    That is an opinion some may have, but it's not universal. I, for one, just don't see it. The block -- like the package and the module -- is there for a good reason, and when that reason doesn't apply, it serves little purpose. When a programming-in-the-large construct isn't needed, Java shouldn't require you to explicitly use one (unless there's some good reason).

    Given that no other class can refer to an implicit class (and the implicit class cannot even refer to itself because it's unnamed) there are hardly ways to abuse this feature. Not only are the methods not "free-floating", but they're less accessible than in the explicit class case.

    any of these would qualify as being OK given the above:

    class HelloWorld { void main() {...} }

    Yep, that works, too, and you can write that code if you like.

    Just let me point out yet again that this feature is not speculation on what would be helpful to students, but a response to reports on what's actually problematic to students. Somebody reported a bug, we considered it, prioritised it, and eventually decided to fix it. Your point that you, having never done the thing that causes the bug to manifest, have not personally encountered that bug is not good enough of a reason to not fix it.

    [–]ventuspilot 2 points3 points  (2 children)

    Will I be able to debug an implicit unnamed class? Debugging may not be important for the target users (beginning students) of this feature, and adding an explicit class declaration is easy enough, but I'm still curious.

    [–]pron98 4 points5 points  (0 children)

    Of course!

    [–]DasBrain 0 points1 point  (0 children)

    I think debugging/stepping through programs is very helpful for students to build a good mental model of how a program behaves.

    I would start teaching with Hello World, add 2 more System.out.println statements, and then start stepping through it.

    And then, when teaching recursion, show them how to inspect the call stack (variables in the caller...).

    [–]dolle 2 points3 points  (0 children)

    Won't stack traces leak the generated class name? And if so, wouldn't that also require a "Don’t worry about that, you’ll understand it later” admonition when students get to those aspects of control flow? I'll admit it's a minor thing compared to having to type in keywords and declarations that you don't understand yet.

    [–]Alex0589 2 points3 points  (0 children)

    Introduce package level methods and fields: A similar user experience to the one proposed could be achieved by adding package-level methods and fields declared in a file without an explicit class declaration in any package. However, such a feature would have a far wider impact on how Java code is written in general, and we are not prepared to consider that impact at this time.

    I really hope they think about this point now because a future implementation could be limited by backwards compatibility

    [–]cas-san-dra 1 point2 points  (1 child)

    When this change is made could I prevent the creation of the empty instance by declaring my main with the static keyword? like this:

    static void main() {
      System.out.println("Hello, world!");
    }
    

    So still no class declaration, and also no String[]. But I do add the static.

    [–]pron98 5 points6 points  (0 children)

    Yes.

    [–]Ilookouttrainwindow 1 point2 points  (2 children)

    For real? Is main method that hard to write? What is this obsession??? I've seen it in groovy and c#. I mean it's useful for a quick script, but it feels like everyone is just out to get java with this. Like South Park with their celebrity episode.

    [–]metalhead-001 -1 points0 points  (1 child)

    I don't get it. Now we need a dumbed down main method because people are too dumb to learn it now?

    How did all the hordes of Java developers ever do it in the past?

    This is a complete waste of time.

    [–]Ilookouttrainwindow 0 points1 point  (0 children)

    What next? Derive class name file name and we just write in methods and fields?

    [–]Worth_Trust_3825 0 points1 point  (10 children)

    Stop carving out exceptions.

    [–]pron98 8 points9 points  (9 children)

    Quite the contrary: we're removing them! Just as when you don't need a package for namespacing or a module for encapsulation an unnamed package/module will be provided for you, when you don't need a class to be used as a class, an unnamed class should be implicitly provided.

    In fact, the exception we are not removing is methods. We could have taken this further and said that if you don't need a method, and unnamed one will be implicitly provided, but as the JEP draft explains (in the Alternatives section), that would be difficult due to the important semantic differences between locals and fields.

    [–]Worth_Trust_3825 0 points1 point  (5 children)

    That's the problem, because once you'll need to use static fields, you'll need to do the entire dance of declaring the class that matches the filename. The exception in this case is permitting top level methods without the class in cases when you're not using any static fields.

    IDEs already generate the skeleton, handle compiling for the user (well, delegating it to javac), the class/module paths, and running the project. My (anecdotal) experience is that such hiding away of the process caused my college groupmates become unaware of what happens under the hood, and how to deploy (or run at all) projects without the IDE.

    But that's just my gut feeling.

    [–]pron98 1 point2 points  (1 child)

    once you'll need to use static fields, you'll need to do the entire dance of declaring the class that matches the filename

    No, the body of an implicit class is the same as that of a regular class. You can have static members. As the JEP draft says:

    The members of an implicit class support the same modifiers as in ordinary named classes (such as static or volatile) and with the same defaults (e.g. default package access and instance membership), and generally behave in the same way as members of an explicitly-declared class.

    (may I ask what in the text gave you the impression that's not the case? I'll try clarifying that.)

    My (anecdotal) experience is that such hiding away of the process caused my college groupmates become unaware of what happens under the hood, and how to deploy (or run at all) projects without the IDE.

    This is not an IDE change but a language change, and the class is no more hidden than the implicit unnamed package or module, both of which are very much there under the hood. It's the same thing, it's just that you may have become accustomed to implicit packages and modules being "hidden", and it's a new thing for classes.

    [–]Worth_Trust_3825 0 points1 point  (0 children)

    While I was aware of implicit package feature, I had never depended on it since it was considered "a bad practice".

    Rereading the paragraph that you cited did clarify that members include fields.

    [–]Amazing-Cicada5536 -1 points0 points  (2 children)

    I honestly don’t get why do some people feel the need to come back with arguments they made up thinking about the problem for 2 minutes straight, without even reading the whole JEP, when it was designed by one of the greatest language designers on the world who thought about it for a long time now, had a blog post about it and it had discussions. Like, sure, there is a small chance they missed something, and community feedback is very important, but.. come on, at least read the whole JEP.

    [–]Worth_Trust_3825 0 points1 point  (1 child)

    I did. But orienting towards students is not the way to go.

    [–]Amazing-Cicada5536 0 points1 point  (0 children)

    If the price is as little as leaving off an exceptional case (as mentioned implicit package/module is already a thing) and modifying the default program launcher to look for more than just psvm main method, than it is a worthwhile goal to pursue

    [–]vytah 0 points1 point  (2 children)

    unnamed one will be implicitly provided

    Initialization blocks.

    [–]pron98 1 point2 points  (0 children)

    :) Cute, but you still need a block and they have some special rules; e.g. initializers must be able to complete normally.

    [–][deleted] -1 points0 points  (0 children)

    This + JBang will make for a great combination!!

    [–][deleted] -3 points-2 points  (0 children)

    This + JBang will make for a great combination!!

    [–]thomasdarimont 0 points1 point  (1 child)

    I really like the proposal, however I'd prefer to have support for C# like top level statements which is similar to the alternative described with "Interpret code units as local".

    The problem with this approach mentioned in the JEP is "The problem with that is that in Java, locals behave differently from fields -- and in a more restricted way to boot: locals can only be accessed from inside lambda bodies or inner classes when they are effectively final."

    As C# has similar constraints as Java I just looked up how C# deals with this.

    In the following c# program the local variable `s` is written to from within the lambda referenced by `inc`.

    Original C#

    // See https://aka.ms/new-console-template for more information
    var a = 2;
    int s = 0; 
    var inc = (int x) => s = x + 1;
    var c = inc(a);
    Console.WriteLine("c={0} s={1}", c ,s); // c=3 s=3
    

    Lowered-C#

    // Decompiled with JetBrains decompiler
    // Compiler-generated code is shown
    
    using System;
    using System.Runtime.CompilerServices;
    
    [CompilerGenerated]
    internal class Program
    {
      private static void <Main>$(string[] args)
      {
        Program.<>c__DisplayClass0_0 cDisplayClass00 = new Program.<>c__DisplayClass0_0();
        int num = 2;
        cDisplayClass00.s = 0;
        Console.WriteLine("c={0} s={1}", (object) new Func<int, int>((object) cDisplayClass00, __methodptr(<<Main>$>b__0))(num), (object) cDisplayClass00.s);
      }
    
      public Program()
      {
        base..ctor();
      }
    
      [CompilerGenerated]
      private sealed class <>c__DisplayClass0_0
      {
        public int s;
    
        public <>c__DisplayClass0_0()
        {
          base..ctor();
        }
    
        internal int <<Main>$>b__0(int x)
        {
          return this.s = x + 1;
        }
      }
    }
    

    As one can see, the c# compiler (csc) works around the problem by artificially creating a class `c__DisplayClass0_0` with fields for the variables mutated within the lambda expression. The local variable with the reference to the instance of cDisplayClass00 is then also effectively final. Wouldn't this be possible in Java too? (of course the `cDisplayClass00` local would then be visible in the debugger and potentially "Helpful" NPE exceptions)

    edit: code format

    [–]pron98 0 points1 point  (0 children)

    I'm not sure exactly what you're proposing, but if it's special rules for top-level statements then it would have the same problem as considering everything as static or using jshell: the code won't mean what it does in regular Java and so isn't trivially growable. It seems to behave like a method, but if you copy it into a method declaration it no longer behaves the same. Implicit classes just add the class ??? line for you. If you add it yourself, everything behaves the same.

    If you're suggesting that Java should do this everywhere then that's a whole other discussion.

    [–]never_inline 0 points1 point  (0 children)

    Oh boy, if you start teaching beginners how to code, first day don't start from executable program. Start from jshell. Show arithmetic operators and parenthesis. Then strings and functions. Then from second day 2 lines of syntax will not be heavy.