Public Static Void Main(string[] Args) Is Dead
Key topics
The article discusses the recent changes to Java that simplify the 'public static void main' declaration, sparking a debate among commenters about the merits of reducing boilerplate code versus the value of explicitness and structure.
Snapshot generated from the HN discussion
Discussion Activity
Very active discussionFirst comment
20m
Peak period
136
0-6h
Avg / period
20
Based on 160 loaded comments
Key moments
- 01Story posted
Sep 16, 2025 at 12:42 AM EDT
4 months ago
Step 01 - 02First comment
Sep 16, 2025 at 1:02 AM EDT
20m after posting
Step 02 - 03Peak activity
136 comments in 0-6h
Hottest window of the conversation
Step 03 - 04Latest activity
Sep 19, 2025 at 2:38 PM EDT
4 months ago
Step 04
Generating AI Summary...
Analyzing up to 500 comments to identify key contributors and discussion patterns
Want the full context?
Jump to the original sources
Read the primary article or dive into the live Hacker News thread when you're ready.
Released in Java 21
https://openjdk.org/jeps/445
It would make Java a much better language in my eyes if it allowed package-level methods, or even multiple records/classes per file. But apparently "impact on how Java code is written in general" is not wanted.
Also of course the misuse and overuse of classes when designing systems, but the complexity at design time is also the counterpart of the ease of use of well designed APIs. I remember using an IDE to write some code and it skipped the whole documentation and run/compile error phase, I could just cast mismatching types as needed.
Probably C# and Swift/Objective C would only be above Java as top languages, being actually funded by paying customers instead of used by companies that depend on volunteer developed open source software and end-users that equate paying for software with evilness.
Everything beyond 8 has been nice to have but 8 was the big one.
(I'll ignore Kotlin... I don't get why people like it.)
Fast forward to around 2020 and I had to organize a team to build search engine in JVM. Given how hard it is to find decent Scala developer I surrendered and did this project in Kotlin. Java devs easily pick up and write sensibly FP-style even code, and builtin coroutines are cool. Even though I had to open up the internals of coroutines to get tracing to work they felt a very welcome change compared to say monadic explicit async.
So for me Kotlin is kind of watered down Scala for typical Java folks and I could tolerate it compared to perspective of writing plain Java.
That's a deal-breaker. If you can't tie together a few values in a record/struct without being forced to box them/heap allocate them, the language will never be used anywhere where you even remotely care about performance.
This is not a difficult problem to solve - C# did it in a very elegant way with structs, and as a direct result, probably for half of all videogames written today, the gameplay portion is written in C#.
Heh, I once had to work in a code base that used an `Integer premiumDefenseLevel`. It contained the level of premium defense a player had purchased, or null if the player didn't have any levels of premium defense purchased in the recent times.
This was in fact annoying to remove, because a 0 after a 1 was treated differently than a null some time for advertisement reasons: Someone who had bought premium defense in the past is more likely to re-buy than someone who didn't, so they are pestered with ads. But it eventually turned into a neat little domain object.
On my university no one got Sun's marketing money in 1998, yet the distributed systems, compilers design, and graphics programming, all adopted Java as the language for new teaching materials, as it sorted out several problem with the assignments.
Both awt and then Swing were pretty bad for anything beyond toy programs, though.
Which is what the respective department was doing before.
Swing is great, it does suffer from bad defaults though.
Anyone serious about it, would be getting books like Filthy Rich Client, and additional libraries like JGoodies.
Granted, they only came to be around Java 1.4 timeframe.
Swing was nice to program, but had sluggish reaction time and more than a few bugs (speaking of Swing 0.9/1.0, never went much further).
For a very long time it completely stagnated and all the features we see added now should've been there 10 years ago, at least, and a bunch of other improvements on top. All because "our goal isn't to adopt the strategy of less successful products, but to forge our own" which now turned into busily adopting all the features that the "less successful products" have had for years: https://news.ycombinator.com/item?id=28985688
part of my dislike is probably that I'm a math person, and the lack of operator overloading really makes any math not using the built-in types dreadful to read.
For the longest time Java had been very keen to be explicit, to the point of needing a log of cruft where it just felt like the compiler was checking you spelt every letter of the incantation correctly because both the compiler and you knew unambiguously what simple thing you were trying to achieve. But this tone changed in Java around the time the new entrants like Kotlin started taking over as what you develop in in a way that scala and clojure never managed. And suddenly all the get-out-of-your-way of lambdas saving you typing out classes and anonymous classes arrived and Java became a much nicer experience imo.
No reason apart from the framework epidemic that's supposed to make things easier for developers, but in the end hamstrings them and weighs everything down.
(to the downvoters - I am a java developer and this is very real to me at the moment!)
I wouldn't consider OO the way Ruby and other actually well designed languages do it flawed.
Or, Ruby is a cute (mostly subset of) Perl.
And after some Kotlin I must say: Kotlin is an acceptable "Ruby with static types".
C# does this well by letting you OOPfy your other code but doesn’t require you to use OOP for this monstrosity.
The same things people use free functions for in any other programming language.
I'm visibly shaking at this statement. What are you even saying here? A function is the most basic, fundamental unit of code organization. What Java does with its forced classes is a complete perversion of computation, sanity and anything reasonable.
It's somewhat implicit in the JVM spec, but functions are always bound to classes as methods. [2] The only kinds of heap objects you can have a reference to are class instances and arrays. [3]
The lack of free functions is really only a minor inconvenience for language implementers. Clojure, for instance, just compiles new classes to hold functions as methods.
From a programmer's perspective, you can write lambdas, but again, it's just syntactic sugar over an inner class.
[1] https://www.happycoders.eu/java/main-method/ [2] https://docs.oracle.com/javase/specs/jvms/se23/html/jvms-4.h... [3] https://docs.oracle.com/javase/specs/jvms/se23/html/jvms-2.h...
[1]: https://steve-yegge.blogspot.com/2006/03/execution-in-kingdo...
https://openjdk.org/jeps/512
It's just syntactic sugar.
What's now permitted is:
1. a simpler way of declaring a main method on a class -- you don't need the public or static, and the args is optional, so you can declare a `void main() { ... }` method on a constructable class;
2. declaring a main function (and other variables/functions) outside of a class -- here, the startup code will handle calling the main function, although I don't think the ability to call anonymous functions currently extends outside of the main function/file.
It reminds me of the attempt at removing Richard Stallman from the FSF, yeah, you could do that and fix a problem, but then what you are left with isn't really the same thing as it was before, it's now actually the same soulless thing as the rest of the competing things.
Saving grace is that obviously, you can still recite the incantation, it's not like public static void main(String[] args) is gone, just that you can skip it.
I think this is the exact audience for this change: for newbies in day 1 of 10 years in their programming journey. Less boilerplate to just swallow, less time spent debugging an otherwise-fine lab exercise if not for the wrong instantiation of Scanner, more time actually focusing on the basics they should be focusing on.
Granted, I still think Java is a horrible first language to learn from or teach with but this is a step in the right direction. Might revisit this opinion in a few years, who knows.
Oh also, we use Java in production so we also have a bunch of ad-hoc "scripts" written in Java for mostly one-off interactions. Nonetheless, these scripts can get unwieldy fast. You'd think I'm exaggerating the benefit here but I, for one, welcome one less level of indentation in these scripts.
Fwiw, other JVM languages like SCALA have already done this exact thing way before. But whatever, it isn't either good or bad. And I can still use the old way out of respect for tradition.
To each their own
> 1: When I was a Freshman in High School I asked a Junior what it meant. He had no clue.
OK... so it's confusing for juniors. A lot of stuff is. I probably didn't know what it all meant when I started either, but so what? You copy and paste it and move on. Eventually it makes sense. Not a big deal.
I don't like Java, and the excessive boilerplate is a big part of that opinion. But it was never nearly as arcane as some people here are making it.
But if you teach people using Java, you have to teach them to write this:
...instead of just: The latter is easy for a student to understand. With the former, you just have to tell them to use it without understanding it, and that they'll understand it later.When they start with the old style there is an overload of concepts where the teacher just have to say "ignore all this", which is not ideal. With new style they grasp fewer concepts at first.
I'm not truly convinced this is such a big deal, but I lived through my university switching from Pascal to Java in the first programming class, and I can confirm people did get much more confused during the first few classes (to be fair they got way less confused later not having to deal with pointers tho).
"public static void main (String[] args)" teaches A LOT if one takes the time to inquiry about every keyword in there.
I learned Java only after Python and I remember being not quite familiar with types so even the 'void' and 'String[]' where a bit mysterious. After learning basic types that part made sense. Then you start learning about Classes and objects, and you understood that main is a static method of this class Main that must be required somehow. As you dive deeper you start learning when this class is called. In a weird way what started as complete, unknowable boiler plate slowly evolved into something sensible as you began to understand the language better. I have no doubt that seasoned Java devs see a lot more in that invocation that I do.
Good riddance though!
The answer is: infinitely much. You could have to write each character in strings as separate characters for example. It would be absolute utter madness but it "would make sense later".
As we become more and more acquainted with programming, a lot of what we do why we do it is incoherent nonsense to a beginner, but important nonetheless.
The limit is actually your time and effort. But nobody likes to write optimal assembly by hand, the balance has to be struck somewhere.
You can't really escape String[], which imo is fine. It's better than argv/argc in C at least.
Thus, many sub-optimal project coordination approaches ended up fighting the design patterns. Java is a good student language, but there are so many better options now... with fewer footguns, and without Oracles farts. =3
As much as I love hating Oracle, they pushed the language forward much more than Sun ever did.
The only reason Java is still somewhat relevant is ironically Android/Kotlin, and SAP/heinous-dual-stack-blobs product lines.
Best regards, =3
>high--frequency trading systems
Probably not the Java stack itself, given GC latency and precision timing skew would translate into millions of lost dollars a second. However, people do silly things in the wrong languages all the time. =3
It did look weird, of course, but they're also using Go (which iiuc has worse GC latency) or other garbage-collected languages (OCaml being a famous example).
I guess it is like using a Fiat Coupe as a gravel dump-truck. lol =3
Tend to deprecate Java services for a number of other reasons =3
Java/JVM is literally everywhere. And let me get this clear: not a fan of both java-the-language and java-the-culture.
Most Enterprise level Java I saw was not clean OOP, but rather a heinous kludge sitting next to a half-baked design pattern. The 3.6B Android OS users in the world probably are more relevant in terms of development projects, and keeping your team staffed. Good luck =3
Besides, what is "clean OOP" even?
Thus, people that actually leveraged the OO paradigm properly, and in a way that may be sustainably regression-tested/maintained over many continuous integration cycles. That kind of "clean" code tree usually only needs juniors to study around <5 files to understand even the most complex modules operation, helps mitigate bugs, and team-leads can weed out quality "issues" in minutes.
People that churn teams usually discover a YOLO and OO paradigm are fundamentally incompatible concepts. People won't know everything they need in the first release, and they will have stuff they don't need but now have to live with by the third release.
This is not a Java specific problem... but it does make it easy.
Nothing integration "teams" do will likely matter much compared to a 3.6B user-base policy change. Have a great day =3
"Nor would a wise man, seeing that he was in a hole, go to work and blindly dig it deeper..." ( The Washington Post dated 25 October 1911 )
Pulling the oracle card when java is mentioned is a useless stunt.
Do you actually use that option at enterprise scale? =3
https://openjdk.org/groups/vulnerability/advisories/
https://app.opencve.io/cve/?product=openjdk&vendor=oracle
It’s much better than ideal.
Depends on the use-case, but I also like Elixir/Erlang, Julia, and Go.
Not all are very popular, yet each offer something uniquely beautiful. =3
(One might argue Go comes close, though)
Javas selling point is that it can do everything reasonably well and has a huge talent pool.
(I somehow mostly avoided learning Java, and my last passing contact with it was 20+ years ago, so these are honest questions).
The main function can be written with `String[] args` if you need it.
This is a decent summary of the changes:
https://www.happycoders.eu/java/main-method/
Further details:
https://openjdk.org/jeps/512
This looks like a hack just for the main file, it would have been good if these functions can be called from other files.
The IO class is good. The rest is information hiding. Now if you could write anything else in Java in this form,it would make sense.
As much as C++ has a lot of problems, them and other languages (python/ruby/etc) never denied that the procedural world existed, while Java wants to blindfold you and push you through a corridor until you get out of it and into the "perfect (not) OOP world"
Each invocation of the jvm requires that you specify the class for which a single static main exists. The other classes containing other static mains are irrelevant.
Interestingly, those two languages use very different mechanisms for top-level functions - although I’m not sure if there’s a significant difference in practice.
Python has true standalone functions, whereas in Ruby’s they’re really methods of a `main` object.
If you're speaking of `__main()`-style entry point, though, you're right, and Java makes it... complicated.
1. Programmer A creates a class because they need to do create an entry point, a callback, an interface... basically anything since everything requires a class. Result: we have an class.
2. Programmer B sees a class and carelessly adds instance variables, turning the whole thing mutable. Result: we have an imperative ball of mud.
3. Another programmer adds implementation inheritance for code reuse (because instance variables made factoring out common code into a function impossible without refactoring to turn instance variables from step 2 into arguments). Result: we have an imperative ball of mud and a nightmare of arbitrary dynamic dispatch.
At some point reference cycles arise and grandchild objects hold references to their grandparents in order to produce... some flat dictionary later sent over the wire.
4. As more work is done over that bit of code, the situation only worsens. Refactoring is costly and tedious, so it doesn’t happen. Misery continues until code is removed, typically because it tends to accumulate inefficiencies around itself, forcing a rewrite.
While the teaching is partially to blame, i say it is more that most people are sloppy and undisciplined thinkers. When they dont have any incentive to produce disciplined code, they wont.
And yeah, it was pretty cool looking back on it later and realising I knew what it all meant!
And yeah, good riddance nonetheless!
I also remember casts all over the place in Java because polymorphism wasn't OOP enough.
And then lambdas and functions were not OOP enough to be first class values and that's why we needed numerous "verb-classes" everywhere.
And of course printf() is not OOP enough...
I dont find Java's first versions well designed. The JVM was quite well designed, but the language not.
And changing a popular language is hard. I think Java's dev do it very well (the process of changing it IS "well designed"). But still the language itself suffers a lot from the bad choices in the beginning.
I like Kotlin: an OO language with as much FP in there as makes sense for an OO language.
If you can't have other top-level functions in Java, then it's a special case, which is ugly.
I assumed this meant that you could have free functions, but you're saying you can ONLY have `main` as a free function? Ok, then I agree this is also garbage.
```Top-level members are interpreted as members of the unnamed class, so we can also write the program as:
String greeting() { return "Hello, World!"; }
void main() { System.out.println(greeting()); }```
I write "return 0" at the end of main in all my programs if that end is reachable.
Decompiled example: https://lab.razor.fyi/#41rAyMUVUJSfXpSYq5dcLDSRsbQ4My9dIbiyu...
> lipstick on a pig's turd
There are several valuable compiler transformations that happen under the hood in languages like this. Closures as types, iterator/generator functions, async state machines. This is just another example.
As a java guy and think python is weird, I don't think this sucks.
But, I also agree that can serve as terrible intro to programming if you start programming right away without understanding the basics of abstractions. But, often when we have tools either designed for a purpose in mind or a dominant paridigm or reaction to existing set of tooling, this can result in understandable yet extreme abstractions.
Java is designed with OOP in mind and it kind of makes sense to have the user to think in terms of lego blocks of interfaces. Every method or class needs to have clear understanding of its users.
public - software handle is for all users
protected - software handle for current and extending classes
default - software is exposed to current package
private - software is restricted to be used in current class alone and nowhere else
So, the beginning of java programming starts with interface exposed to the user or other programmers. Is it weird and extreme. Yes. At least, it is consistent.
You can just say initially e.g. when I learned C++ that "#include <iostream>" can be "mostly ignored for now, but just know iostream stands for Input / Output stream, and this line is necessary to e.g. output with std::cout"; and there are no scars left from this.
Java choose to adopt object oriented purity in a very weird way. Sun has initially rejected the idea of standalone functions (static import was introduced in Java 5, closures in Java 8 and compact source files/instance main is only coming now). Even with static imports and compact source files, there is still a class holding these methods behind the scenes (for practical and compatibility reasons, more than to achieve any ideological or theoretical goals at this point). That seems like Sun was trying to keep the purity of "everything is an object", but at the same time they've introduced primitive values, which are clearly not objects. This was a pretty bad decision in my opinion. There is no practical benefit from requiring every function to be defined inside a class[1]. On the other hand, being able to have methods defined on an integer is a pretty nice feature.
If we look at a Smalltalk, which is generally considered be an example of a "pure" OOP language, we see a striking difference. This is Hello World in Smalltalk:
Smalltalk allows you to freely define functions outside of classes and even write code that is not part of a class (directly in the REPL).[1] https://steve-yegge.blogspot.com/2006/03/execution-in-kingdo...
We even have design patterns like Command, to workaround first class functions in "pure" OOPy way.
And for enterprise software development, I like it that way. It can make up a definition it wants and stick to it. I think it is better for a language's ecosystem and culture to have one dominant paradigm than becoming kitchen sink of programming languages.
Edit: added a link
[1] softwareengineering.stackexchange.com/questions/264697/alan-kay-the-big-idea-is-messaging
Please show an example.
How does it affect you this change day to day?
(Though the ultimate conclusion of this line of thinking is that programming 101 courses should be taught in as concise and syntax-light a language as possible, giving the learner as few opportunities to screw up the input as possible. I’m a fan of teaching programming in Ruby, personally. Not theory of programming, mind you; just programming as an iterative human process.)
100% this. To make Java be the all-language makes it a mess without a defined goal. It is better to start learning with a language better suited for it. And then the learner can specialize and expand to other languages. This also helps to create awareness that different languages have different use cases.
Now that I think of it I rarely even write a truly new class from scratch, usually you just implement/extend some framework-specific thing.
I mean even this part:
``` var name = IO.readln("What is your name? "); IO.println("Hello, " + name); ```
is _worse_. `IO.readln` doesn't tell you whether that's file I/O or stdin/out. The more explicit the better, if you ask me.
public static void main(String... args)
43 more comments available on Hacker News