Hacker News new | past | comments | ask | show | jobs | submit login

I'll bite, I tried Java after a while fully open to giving it another shot but ended up being deeply disappointed. It seemed that the language was still stuck in the 90s and features came from the frameworks so there was nothing in the language but all you need to do was learn framework/s and how to use this framework with that library and so on. Storing a date as an ISO UTC by default and sharing it with Json needed layer upon layer of code.

There are no easy ways to build abstractions so it's all annotation upon annotation or back to design patterns of composition / inheritance.

Do not even get me started with Gradle/Maven where declaring a custom task is a mini project.

The language still has old world problems, anything can be null, no easy way for structured concurrency and everything is mutable. Top that with verbosity of using lambda, streams etc and it feels like half of the time in spent in fighting /learning the language or framework and half implementating a feature.

I still think JVM is great, and Kotlin and Clojure offer much more out of the box, but using plain old Java in 2024 is just painful. Most people stick with it because "achitects" (who coded last in 2011) like it and/or people have not tried any other modern programming language and stick with the tried and tested.




> Storing a date as an ISO UTC by default and sharing it with Json needed layer upon layer of code.

Storing it in a database, I assume?

It feels like your didn't like a framework instead of Java. "Manually" parsing JSON, parsing a date, and inserting into a DB really only needs a couple of lines. Assuming you've set up HTTP and DB libraries, of course.

I agree that maven and gradle are annoying, but I've never liked any build tool I've ever used.


Yeah AFAIK every orm will easily store an Instant/Date/LocalDateTime pretty easily into a database. And serializing them with any JSON library just works out of the box.


Interesting perspective. Some of it I agree with, but not all of it.

> There are no easy ways to build abstractions so it's all annotation upon annotation or back to design patterns of composition / inheritance.

What are your top 3 abstractions that are hard or impossible in Java?

> Do not even get me started with Gradle/Maven where declaring a custom task is a mini project.

Agree on Maven, but the criticism I most often hear for Gradle is that it actually makes it too easy to define custom tasks (mainly from people who like the standardization provided by the stricter Maven guardrails).

> [...] anything can be null, no easy way for structured concurrency and everything is mutable. Top that with verbosity [...]

Maybe check back in a couple of years, many of these are in the process of being addressed!


I'm hoping the declarative gradle stuff works out. It should simplify it a bit. https://declarative.gradle.org/


One of the problems with Gradle that it keeps changing.


I don't agree. Grade in Kotlin was a godsend.


It's telling that you prefer Kotlin and Clojure. The few languages that are as popular as Java or more (JS, Python) have most of the problems you mentioned and more (and some newer languages, like Go, too). I.e. the vast majority of new software written in 2024 is written in languages that you think are "painful" and outdated. Quite a few of those who prefer these languages have actually tried languages that are richer (or mainstream) -- i.e. those that you call "modern" but some of which predate Java or are of the same age -- and found them inappropriate for their usecase for various reasons.

The thing is that programmers simply don't agree on what they want to have in their programming language. Some are absolutely certain that they need feature X and others are equally certain that feature X would make things much worse. They have contradictory views on what's better. But their preferences are not evenly distributed, and some views are held by more people than others. Languages that aim to be very popular need to target the majority view, and it doesn't matter whether majority views are justified in some objective sense.

But it goes further than that because the goal of a programming language is to produce software and the goal of software is to produce value that is usually measured in economic (i.e. monetary) terms. For a language to maximise monetary values it must accept some environmental realities, such as that most programmers who will be writing the software to produce monetary value are relative beginners, and so a language that is less attractive to beginners is likely to be less valuable, and so less succesful in the market.

That is why you see that over time, Java adopts more and more features that were present in ML (in retrospect, arguably the most influential typed programming language ever) in the mid-seventies. But that's not to say that ML is more modern or even that in 2005 it was "better" than Java, only that the preferences of the broad market have shifted over time so that certain features that were in ML in the seventies only became valuable to the market much later. That's why Java's designers, who knew ML back when they designed Java, chose to adopt its features only very gradually (Java's generics, lambdas, type inference, records, and pattern-matching all came from ML). Did those who picked ML to write their software in 2003 end up better off than those who picked Java? I don't think so.


I don't think Java is as prevalent as it is because it's quote-unquote "preferred" by developers...

There's a difference between being prevalent and being popular.


It's not necessarily preferred in the sense that those who think a lot about programming language think of language preference (i.e. like the preference of a connoisseur), but it is, nevertheless preferred because most programmers don't think of programming languages like programming language fans do (or, indeed, as much). A language can be preferred because it happens to be what you know and you're interested in writing programs rather than learning more languages, and it is the language you know because it's the language you've been taught, and it's the language you've been taught because it appeals to those who choose what languages to teach.

Evolving the design of very successful languages requires a different kind of thinking about programming languages than that of programming language fans, who don't usually think of maximising economic utility in a certain market environment when they think about what they like in a language.


I don't think one needs to be a "connoisseur" to prefer something other than Java.

I also don't think Java appeals to those who choose what languages to teach.

IMHO it's just a self fulfilling prophecy. A combination of it being widespread in the past, there being jobs for Java because of that, employers expecting students to learn it, students expecting to be taught it, and professors sticking to what they know.

Again, in my opinion, viewing any of those as a valid reason for choosing to use/learn/teach Java implies favoring convenience over value. I prefer not to do that, but I understand people have different views of the world and belief systems...


> IMHO it's just a self fulfilling prophecy.

Except C++ was once more popular than Java, as was Visual Basic. PHP was almost as popular and Ruby was on its way. Java is quite exceptional in how long it remained as popular as it has, so clearly popularity can't explain its own longevity.

> viewing any of those as a valid reason for choosing to use/learn/teach Java implies favoring convenience over value.

Well, the software market is under heavy selective economic pressure, so you'd expect things that actually provide value to spread rather quickly. Indeed, things like unit tests and GCs -- once they met a certain level of "production quality" --spread very quickly, and now it seems like various AI assistants could end up another such example. So if something doesn't spread quickly, it's fairly safe to assume that it doesn't really offer the value the market cares about.

It's like the story of VHS and Betamax, where, at least according to the popular story, Betamax fans thought it was of superior technical quality because of its better picture, but VHS's technical superiority was in recording time, and ultimately the market saw more value in the latter than in the former.

Java's evolution is being designed very carefully, and we at least try to select features that we think could offer real business value -- which also includes not just theoretical power, but the actual ability of most programmers to put a feature to good use -- and not to introduce features that we think are cool (or those that we feel like we're trying to rationalise their value). Of course, we don't always stick to that, but we try (popular languages are generally stingy with features because there's a pretty clear negative correlation between language "richness" and its success). You may think this is obvious, but designers of less popular languages often very much don't think like that at all.


Being a moderate, lowest common denominator language does have its own value, though.

It's easy to reason about, easy to hire for and easy to pick up if you know other mainstream languages. It's not just the chicken-egg market dominance thing you're describing.


> Being a moderate, lowest common denominator language does have its own value, though.

I'd argue that's Python, not Java


Can there really be only one LCD language?

I guess theoretically based on the metaphor, yes, but for all of Java’s faults, it never asked me to swallow the poison pill that is significant white space.

Which is to give immediate lie to the idea that there can be only one, Highlander style.

Also, maybe things have changed but I find it hard to believe that Python’s performance profile is strictly competitive (though I don’t love Java’s memory outlay either). And I’ve never heard or seen a Java development setup guide start with “first install a Java version manager” either.

It should go without saying that YMMV, but this site seems to get more cantankerous by the day.


It can be both, but I'd say having types for the arguments in your method signature is more "moderate and safe".


As someone who is knee deep in Rust daily, I couldn't agree more...


It's worth noting that you're a Java dev, working on OpenJDK at Oracle (per your profile here). Which is to say, your bias is....pretty extreme.


I don't think I have any more bias than any other programmer. But I do have some insider insight into the considerations that go into the design of popular mainstream languages.


> I don't think I have any more bias than any other programmer.

I do not agree at all, but to each their own!


> I don't think I have any more bias than any other programmer.

Oh my. Quite the tell.


Kotlin is a good way to make a lot of Java frameworks a lot nicer to use. Extension functions can smooth over a lot of boiler plate. Spring Boot is a good example of that. Using that from Java is a form of masochism. Using it from Kotlin is just a lot nicer and easier. Spring has had excellent support for Kotlin out of the box for many years and even before that it was already quite nice. I made the switch about six years ago and haven't looked back since. I have been using Java/jvm since 1995 so I've been there, done that, and seen it all. Not touching any Java a lot these days.

Gradle is not ideal but also not that hard once you figure it out. I tend to use template projects on Github so I don't have to reinvent that wheel every time. And with most build systems once you find yourself extending them, you might want to consider if a simple bash script wouldn't be the better solution. I've seen people jump through a lot of hoops to get docker containers running before they run their tests. That's a 1 line command in a shell. So my github action does : 1) docker compose up 2) gradle build 3) docker compose down. Doing the docker compose business from gradle has zero value for me. But I've done that as well.


I'm being paid to write Kotlin at the moment. I _still_ prefer modern Java and it's what I use for personal stuff.


Regarding structured concurrency: https://github.com/softwaremill/jox

Some part of the Java (and C#) mindset won't change but you can keep the annotation soup to a minimum with modern compile-time libraries (see Avaje, Helidon, ...)

I personally have a bigger issue with how annotations are used in Spring for instance, I don't understand why so many people tolerate stringly typed configuration that gets loaded at runtime.


https://openjdk.org/jeps/453 is also in progress for structured concurrency


Heh, after all the years of "you don't need tasks and async/await" (and performance loss or boilerplate that came with that attitude) Java finally looks to implement them too.


If you dont like Maven and Gradle, you should check out my JVM build tool Mill. Originally targeted at Scala projects, but it can build Java projects as well. It makes declaring custom tasks really easy while still being safe, structured, and performant


You forgot to post a link - I'm cuious to check it out


https://mill-build.org/ you'll need to know some Scala


Yep, the builds are in Scala, but you dont need to be an expert any more than you need to be a groovy expert to use gradle. Anyone with programming experience should hopefully be able to learn enough to be productive with Mill without needing to get to deep (or at least that's what I hope to achieve!)


> you dont need to be an expert

I don't doubt that. Your Scala libraries tend to be simpler than the rest of the communities.


I don't know why I never see anyone mention JeKa when they complain about Gradle and Maven. https://jeka.dev


> Storing a date as an ISO UTC by default and sharing it with Json needed layer upon layer of code.

I've been a Kotlin dude for a very long time, and am a bit out-of-date on other languages.

What are languages that handle this nicely, without needing libraries?


Js clearly


It might be worth one more shot ^_^ I've (unexpectedly) found myself writing a book on modern Java practices (after years at $megacorp), so I think there's some stuff people miss about what's going on lately.

> the language was still stuck in the 90s

The folks who lead Java are doing an awesome job of tugging Java out of the E N T E R P R I S E 90s and into a more "modern" direction (all without breaking backwards compatibility). The long tail legacy will always be there, but the language is rapidly evolving and picking up new modeling and QoL tools.

>There are no easy ways to build abstractions so it's all annotation upon annotation or back to design patterns of composition / inheritance.

This is still a common belief, but it misses some of the cool stuff happening in Java lately. Sealed interfaces and records are amazing data modeling tools.

Those features snuck Algebraic Data Types into the stuffy "90s" enterprise language. Records (product types) and sealed interfaces (sum types) make modeling things pretty seamless. Sure, it isn't Haskell, but it's powerful and, compared to the old way of doing things, phenomenally terse and expressive.

>Do not even get me started with Gradle/Maven where declaring a custom task is a mini project.

Ok. Agree entirely here. Every Java build tool makes me want to pull my hair out. Honestly, even after years of using Gradle, I stil have no idea how to use Gradle. I poke things until it works.

>everything is mutable

Another thing that's changed / changing! Records are shallowly immutable by default. Value classes are on the way (currently a JEP). The collection interfaces are now "null hostile" when you go through the value-oriented constructors. There are lots of ways of controlling mutability in the langauge. Java has evolved into something that lets you control whether you want to talk about identity objects or value objects.

>anything can be null

I've found this is, generally speaking, not a huge issue in modern code. It can be mostly mitigated by convention in code you control. However, definitely an ongoing pain point when interfacing with 3rd party libraries. There are lots of @NonNull annotation processors, but I think they're mostly bad tools. Having null hostility at the compiler level would be a awesome next feature in java (fingers crossed).

>Most people stick with it because "achitects" (who coded last in 2011) like it and/or people have not tried any other modern programming language and stick with the tried and tested

FWIW, I use all kinds of cool "modern" languages (Purescript, Idris, Clojure, etc.). I also use run-of-the-mill stuff like Python. Even with that familiarity, I still think Java is a good fit for many projects. It's boring. It's reliable. Everybody can learn it. Everyone can be trained to write it well (i.e. in a "modern" style). The JVM is rock solid. It's a great language for stuff that just works and doesn't page you at night.


> Having null hostility at the compiler level would be a awesome next feature in java (fingers crossed).

This is being worked on, it seems [1]. I remember it being discussed here not too long ago, but can't find the link right now.

[1] https://openjdk.org/jeps/8303099


It was discussed 27 days ago: Null-Restricted and Nullable Types

https://news.ycombinator.com/item?id=41136974


Complaining about having to learn basic parts of language, while this is true in any platform... sorry but you immediately paint yourself as junior in java with clearly other preferences and dont understand java's basic value proposition.

In the meantime million+ devs will continue churning out the code thats good enough for its purpose. Exactly as business expects, they couldnt care less about any of this.


> Complaining about having to learn basic parts of language, while this is true in any platform...

There’s a difference between obstinately refusing to learn the basics of a thing, versus taking issue with there being a bunch of self-inflicted hoops one must jump through to use a thing.

All other things being equal, I doubt you could put up with a car that required an elaborate 10 minute start up procedure, wherein any mistake pulling a dozen levers, cranking a bazillion knobs, and poking innumerable buttons could result in the engine exploding. If any such car entered the market, approximately zero people would put up with the headache — though I concede that some would likely love such a car, and proudly take the stance that “anyone that doesn’t like it isn’t a real driver”.

The difference is intrinsic vs extrinsic complexity.

When I program, I want to spend as much of my time working on solving the core problem, and as little time doing anything else — whether that’s wrangling unintuitive and poorly documented CLI tools, working around wonky, flaky third party APIs, etc. The value one generates is purely in solving the problem they set out to solve; all of the other hoops they jump through is the cost of doing business. I don’t see how you can fault someone for avoiding tools that (in their estimation) reduces their value to expense ratio.


I'm looking forward to see Kotlin take advantage of more of these new features.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: