Hacker News new | ask | show | jobs
by timmg 1 day ago
I feel lonely in that: I mostly love Java as a language.

The lack of value types is the biggest impediment to certain types of performance. I am really looking forward to this evolution of the language.

12 comments

What I love the most is the sheer amount of thought and philosophy put into Valhalla. It transcends the binary understanding of object vs value and actually defines 4 distinct buckets:

1: Classical Object

2: Object without identity

3: Atomic Value

4: Classical Value (Tearable)

Each bucket has clearly defined performance characteristics and semantic constraints. So depending on the nature of your data, you can always get some benefit from values even if you couldn't go all the way. This is a work of art.

It's work of art and a work of science, I'd say. Programming language dev needs both, and I think Java has learned how to do both, at least compared to its messy early years.

On the note of science, I'll credit Java's maintainers for treating their language as a technology and not merely as a product. Many languages respect the real-world physics of computers to stay relevant. Few respect the "metaphysics" until weird bugs keep emerging in the compiler and ecosystem. Bugs that can't be solved with more building, engineering, or even design. Because those bugs are not defects; they come from the concepts & axioms of the language itself, not its implementation.

this comment reads like a parent who can’t help but love their child unconditionally and uncritically.

That’s a lot of complexity a lot of other languages don’t even need. It’s great Java designers have managed to shoe horn something in, but it’s all because of misdesigns 30ish years ago mispredicting of computer architecture.

I think you've misunderstood, because not only would this have been the right design if it had been in Java since day one as it's in line with the philosophy of the platform, it's also simpler than in other languages.

The idea is that instead of controlling memory layout and referencing directly, you communicate your intent: do you care about this value's identity or not? Do you need atomicity or not? Do you need nullability or not? Once the intent is clear, the compiler is free to choose the most appropriate and efficient layout for the particular value at the particular use site. In other words, you say what semantics you're interested in rather than how to implement them at the lowest level.

This opens up optimisation opportunities that are lost when the programmer directly controls the representation rather than the intent. E.g. in other languages you may say whether you want to pass some value by reference or by value. Here the compiler is free to say, well, if identity and nullability are not needed here, I can either pass by value or by reference, and I'll do whichever is more efficient.

And by the way, your point about early misdesign (whether it applies here or not) also inverts the desired state. Every language makes decisions that will be suboptimal in the environment some time later, and Java certainly has its share (its mutability and nullability default; how it treats serialisation). Rust, for example, was first designed twenty years ago, and some of its fundamental decisions reflect the state of the world at that time (it went all-in on some C++ premises that seemed fine 20 years ago). But since important codebases often outlast the outdatendness of early language decisions (your OS and your browser are running some >30yo code and/or affected by >30yo design decisions), one of the things most important in a language isn't the decisions it makes early on - some will prove "wrong" while your codebase is still alive and kicking - but how well it adapts and evolves. So when you pick a language for an important project today, the language's current state will end up mattering less than how the language evolves in the future. The question asked isn't "will I like this decision today?" but "will I regret this decision ten years from now?" Java is one of the languages with the lowest "regret factor", possibly lowest of them all.

While I agree with the comment being overly-praise-y, this is complexity that any multithreaded language with mutability and reasonable sanity/safety desires (but without intrusive compile-time rules a la Rust) has; others just might pretend some of the options don't exist / aren't desirable. (..and value objects, as landed in the PR, doesn't yet have tearable objects)
I think it really highlights how important it was to have atomicity and integrity by default because even here people will handwave away any such concerns as if they don’t exist.
Your comment makes no sense to me, but I must grant that there is a lot of bad reporting about Valhalla and I’ve been following the mailing lists for well over 7 years now.

Nothing, absolutely nothing about the design is a compromise that would detract from the project if it was for any other language.

You could judge them for bringing “complexity to an easy topic” but it really is far from that and the idea of a value type being a distinct dichotomy from an object is just a convenient tradition.

The push for immutability and value-ness has been going on for a long time and the motivation of the project was to bring performance benefits that align with semantic statements about the underlying data type. Which is of course a more nuanced take than “go value, go faster”.

Classical object, object without identity, atomic value, and classical value are not simplifications that you’d want in other languages. Rust, Haskell, Python - none of them need or would benefit from any of this.
Because?
I used to love Java mostly for its batteries-included well designed standard library. Despite the verbosity of the language itself. But over time the language has really evolved a lot and gotten a lot more pleasing to the eye (in my opinion).
At some point I thought there was no way back compared to C#.

But nowadays I see the language improved a lot, avoided async/await and added virtual threads, added records, now Valhalla, decent lambdas and tons of quality of life improvements.

In the meantime C# became a monster of 2000 ways to declare properties init get, set, backed, not backed, stackalloc, structs, etc.

And I know it is done for performance: but Java is still you have a value type or a reference type. That simple. And now, on top of it Valhalla.

I think Java stayed overall more stable and simple.

C# is still pretty good, but it is just more complicated.

100% agree.

They added so much new syntax to C# to the point it really is starting to feel like C++++ whereas Java has modernized itself without massively expanding its syntax and modifiers.

java the language is amazing

the problem with it is entirely cultural. why is `IStatusChangeEntityCreationManagerFactory` everywhere?

and why are the frameworks so huge and all encompassing? i think batteries included rails-style frameworks are great, but when i wrote Java, it didn't feel like rails at all

none of these are language problems

I know and like Java for almost 30 years now. It is amazing how carefully the language is beeing refined. For the cultural aspect, yes, that is sadly true, but I have the feeling that the culture changes. More and more developers realize that there is a better way now (e. g. records instead of dumb classes full of getters and setters). Maybe the main problem is bloated frameworks and their stickyness. The Helidon framework, for example, is a breath of fresh air compared to Spring. Go developers complaining about huge Java frameworks and boilplate could be happy with it.
IMHO, the main reason why Spring is huge is because it has grown organically to encompass many of the business cases/issues that one may encounter in both depth and breadth. So the http framework supports almost everything you may ever need and there is integration with every database, middleware, infra like kubernetes. (One can debate about the quality of all the lesser used modules but the main modules are pretty okay.)

On the other hand I have used Quarkus which was great until it wasn’t because a certain http feature wasn’t supported or we needed integration with an unsupported database. In enterprise that is enough reason to just choose for the batteries included option and lift along on improvements of the main framework.

> or we needed integration with an unsupported database

How difficult is/was it to add a custom integration?

Just adding the bare bones integration wasn’t that hard. The trick comes from ensuring all the observability is wired correctly, that it fits in the framework usage, works good with graalvm, and other “non-functionals”.

At this point the work is typically more than you want a single team to maintain. Unfortunately, in many large enterprises it is just easier and more efficient to grab a bigger framework than trying to organise sharing the custom integration in the organisation.

+1 for Helidon (https://helidon.io/) - such a great framework, especially the SE variant. Powerful, modern, fast, modularised, and easy to understand.

I'm back on Spring for work reasons but use it for all my side-projects.

i am building my own framework on top of it[1]. the biggest thing for me was it was rewritten on virtual threads from grounds up. no vertx. no netty, lesser indirections.

1. https://github.com/sku0x20/stopgap

I was not aware of Helidon. Looks nice at first sight!
This is specifically Spring culture, not Java culture in general. I don't tend to see this outside of Spring. Maybe back in the J2EE days, but that community seems to be more or less dead.

Java is a big tent. Yeah there are some parts that deserve this kind of mockery.

The Rails equivalent is over-metaprogramming. "I solved it with method_missing." I've worked on code like this in real life. TBH I'd rather have the inane verbose class names.

I**Factory existed long before spring came around
I-prefixing interfaces is a practice from Microsoft's COM, and to this day still isn't part of Java culture, despite the efforts of subversive dotnet renegades.
Yes, more common is

  Manager     // interface

  ManagerImpl // class
Yeah, Ruby code bases are generally harder to maintain than Java ones.
I have an opinion on why. If you were in that world 25+ years ago, you'll be familiar with the landscape. There were a dozen popular application servers, each with 15 versions in the wild, all running on premises, and you had to ship software to customers who had wildly different operations. It helped. It's verbose. As you said, this mostly attributable to JEE and projects that traded build time complexity and home-grown code for abstraction complexity.

I had to support systems from IBM, BEA, Apache, Red Hat, SAP, and some I'm certainly forgotten. Then there were the piecemeal systems. OSGi made an appearance. Then you have databases from Oracle, Microsoft, and IBM. Identity and auth was the wild west, with countless SSO vendors, wacky LDAP implementations, wackier SAML implementations, Kerberos, Ping... Despite that, it was pretty feasible to build and ship the same artifacts and configure things at the site.

Most languages simply don't have all the frameworks that were created specifically for use in an enterprise context. There's cobol and there's maybe C#, Java and then a long tail of everything else.

A lot of the Java stuff actually came out of the Smalltalk community. IBM used to employ a lot of these people and they brought their enterprise stuff with them when things like Enterprise Java Beans became a thing. And because IBM was there, you got everybody else showing up as well. That's why Oracle bought Sun as well to get access to that juicy market.

IBM could have picked any language. But Java was kind of there and new at the time and it kind of did the job. So that's what they jumped on. MS stole a bit of the thunder with dot Net a few years later which is why C# is also very common in that space. But besides that there isn't a whole lot that has similarly wide adoption. Client side is a whole different story of course.

And the reason stuff gets complicated is that there is a lot of design by committee going on in this world by parties that are mutually adversarial and have big budgets.

So, this particular feature comes out of at least 15 (I think) years or so being debated in that sort of committee. It kind of predates the whole inception creation of things like Kotlin. I was at a 15 year birthday party for that at the Jetbrains office in Berlin a few weeks ago. Debates about value classes in the Java community probably go back to last century.

> Most languages simply don't have all the frameworks that were created specifically for use in an enterprise context

And yet a lot of enterprises have done without in other languages.

There's always this comment on every Java post. I expect the average HN member to be someone on the team who is either leading their projects or plays a significant role in driving the design of the software. You set the culture for your own projects. I've lead the development of some massive Java apps and all have had simple and clean architecture. I've never seen IStatusChangeEntityCreationManagerFactory or anything like it even once in any of my projects, but perhaps that's because the last time I used Spring was ~17 years ago. Most of my recent projects are using Quarkus, which is still a relatively large framework. But our codebase is designed in such a way that we're not tightly coupled to Quarkus.

I have seen a surge of overly complicated PRs now that we're in the AI era, but it's our job to be the gatekeeper and push back on this crud from entering the codebase. And that's likely true of any language.

I have never run into code like that in any of my jobs.
Show me where IStatusChangeEntityCreationManagerFactory is in the language. Or the standard libraries. Or anything like it
Spring is not Java. It's also one of the most complex projects out there.
> Or anything like it
Spring isn’t the language or standard libraries.
lol it’s so long it overflows the window and breaks the css on my phone.
it's not, that's my point
You’re not alone! I love Java too. It is excellent.

I don’t reach for it much anyone since I prefer TypeScript’s type system and the ability to use the same language for both client/server, but I’m never upset to write some Java :)

You shouldn't be. I do like Java a lot, and recent changes (and speed of those) just makes it more and more better.

And I appreciate and I'm under huge awe to the amount of though put into the evolution -- instead of just cramming every new shiny thing they ponder it a lot to arrive at the most sensible option while trying their best to maintain backward compatibility -- kudos!

I agree fully. It may not be perfect but it works really well, has a huge community, and I like the language.

I mostly ignore online discussions about Java. So much of it just feels like memes. Complaining about things that haven’t been valid in a very long time. Sometimes almost 2 decades.

It feels a bit like people bashing Nickelback. It was the “cool” thing to do. Maybe they’ve never used Java. Or only for one college course.

People can dislike Java. I’m sure some do. It’s fine. But it seems like the anti opinion is really over represented/amplified.

You are definitely not alone. I love Java and I will always defend it. Java's perception is tainted by baggage from decades ago.
The tooling could be better, though.

I wish it came with more batteries included, and it renovated that old Java cli split per commands, following a bit what golang did:

- java run

- java build

- java test

- java fuzz-test

- java format

- java lock

- java lsp

- etc.

Along with a better support of posix long form flags like ‘--version’.

That will not happen for backward compatibility reasons but a new build tool with a modern CLI would be nice. One that's declarative like Maven (without the XML) and doesn't require an upgrade for every new JDK version like Gradle (screw Gradle).
Maven 4 provides alternative build file syntax with extensions: https://github.com/maveniverse/mason
Is this better than the previous polyglot extension?
Today it is a great language with a runtime that is unequaled. For heavy duty business backend server load, it is the standard choice, and rightfully so.

Do I love Spring? No. Do I prefer Typescript for my little side projects? Yes.

Fortunately, there are plenty of mature alternatives to Spring these days.
What are those alternatives? I haven't touched Java for web development for a very very long time.
Agreed but apparently BigCorp hasn’t gotten the news yet.
I've said this before but I'll say it again: The worst part of Java is Java programmers.

For most of my career, I thought I hated Java, primarily because every piece of Java code I had ever worked with was overly verbose across a million different files to do things that would take like ten lines of code in any other language.

Then I actually started looking at all the features for Java 8, 11, 17, and 21, and realized: NO! Java actually gives lots of really great tools and language features that allow you to write relatively pretty, terse, performant code. Record types help cut down on a lot of boilerplate stuff, the streams API allows for pretty work over lists, sealed interfaces mostly solve my itch for ADTs, virtual threads are genuinely pretty impressive bits of engineering, and for the stuff that isn't built in, Vert.x and Disruptor do a pretty good job filling in the gaps.

Once I learned all that, I was kind of mad at people still writing code like it was 1999, but also started to enjoy writing Java. It helps that by this time I was already senior and staff level, meaning I was given much more leeway in how code was written (so the poor junior engineers are stuck/blessed dealing with my code using all the shiny new features).

> The worst part of Java is Java programmers.

For companies that deployed Java this is the best part. Growth of Java from 1995-2015 and enterprise IT outsourcing was almost in lockstep. It was not for programmers with taste or interest in coding. It was J2EE 1000 page manual printed and distributed in bulk at IT vendors describing things in hugely verbose details with dummy pet-store project to use all facets of Java/J2EE that ingrained into overall Java culture.

It could be business or politeness reasons that well meaning Java language authors rarely spoke a word against this wider Java culture. So it was just assumed that overtly verbose code and organization of Java projects have official stamp to it.

Yeah, I guess I always just found it miserable to work on.

When I worked at a BigCo [1], our project was a big monorepo in Java which had 60,000 folders, and I don't remember how many files. It was decidedly no fun to work on, because everything was spread across a million files and so doing anything required sifting through dozens or even hundreds of files. I hated it.

I've worked on giant projects since then, but they've been written in more modern Java and they are less painful.

[1] It's not hard to find the specific one through my history but I politely ask you do not post it in reply to this post.

I'd say a lot of verbosity comes from generalization -- when you want the code to be reusable and moddable (pluginable). No wonder two widely moddable games (Minecraft and Kerbal Space Program) are written in Java and C# respectively, makes it very easy to create mods. Once I tried to make a Go project at least build-time moddable and found myself creating a lot of java-esque Factories and Builders.

Whether that generalization is premature -- I don't know, just my observation on why.

> No wonder two widely moddable games (Minecraft and Kerbal Space Program) are written in Java and C# respectively, makes it very easy to create mods.

It's more that it's easy to write code that links directly into the game. Easy to do because you can decompile them and make changes easily without having source code. Sure, Minecraft was obfuscated for a long time, but people put a lot of effort into deobfuscation and obfuscation removes a lot less than native compilation.

(You also don't need an official modding API this way)

I don't agree with that though.

I've written plugin systems for stuff I've worked on, and it didn't require nearly the same level of verbosity. Granted, I usually have done this with sockets instead of directly using JVM and reflection. To each their own, but I like using sockets (usually ZeroMQ) for this stuff because then it's completely language independent.

Even if I granted that you needed to use all this factory and builder glue stuff, I don't agree with the typical Java developer's strategy of breaking things up across a million files, which Java at least greatly encourages.

I don’t do programming for a living (i manage infrastructure) but i have a very fond memory of java from the earliest days of my career.

I really really think that java is weighted down by all the ceremonial enterprise stuff that has accumulated over the years.

Lightweight frameworks are somewhat recent, otherwise you really couldn’t print a text/plain http response without bringing up a whole application server and a whole ecosystem of libraries (j2ee)

Also… the build system situation is still shit

You are not alone.

Java remains unfairly tethered to a reputation forged over 20 years ago. Human psychology reveals a reluctance to update our worldview: once a collective consensus solidifies, it becomes very difficult to dismantle. Yet, to dismiss Java today is to overlook a remarkable evolution. Modern Java is an elegant, highly capable language, resting upon the Java Virtual Machine, which is a remarkable piece of technology.