My impression is that the design of Java the language, plus its runtime, are appreciated even by the harshest critics.
However the culture around complex frameworks and over-engineering is what most people really dislike about it.
IMO pretty much all the advantages touted by Java proponents (such as: good language design, easy of use by heterogenous teams, speed, etc) are correct, but are negated by a large part of the culture and ecosystem. The memes about humongous class names and 200-method stack traces are true when you use the popular frameworks and techniques.
Of course there are exceptions to this and this can creep into other languages too, of course.
> However the culture around complex frameworks and over-engineering is what most people really dislike about it.
I think this is it. I remember back in the day being absolutely floored when I started learning J2EE by the, it seemed, unnecessary complexity (for most use cases) of EJB. It was incredibly offputting: if you were starting a project from scratch it felt like you had to do a ridiculous amount of work just to get to "hello world". I'm sure it wasn't that bad but the memory has slightly scarred me.
I haven't worked in Java for ages, mostly working with .NET for the last 16 years and, unfortunately, the same problem has to some extent bled into the .NET ecosystem too.
A few years ago I contracted at a place where the "micro"-service team I was assigned to had this codebase where they'd clearly taken the OSI 7 layer reference model to heart and applied it to a domain where customer details were collected and recorded. I've nothing against layered architectures, and have made use of them many times in appropriate circumstances, but this was awful: one of the most needlessly complex codebases I've ever worked with, and incredibly discouraging to work on because it was so hard to actually achieve anything. There were fully three or four layers in the middle that did nothing but call the next layer down. The quantity of boilerplate was extraordinary. To add one method that did anything of substance you'd actually have to add between five and seven methods, most of which did nothing but call the next layer. Ridiculous.
Still, that doesn't change the fact that the .NET languages, runtime, and base framework are excellent, and that sadly being excellent is no antidote to misuse. Same applies to Java.
That's true. I also used to be a .NET guy in the past, but I started doing more games (and then frontend) when the movement from Rails-ish to Java-ish MVC started.
The thing about the multiple "layers" that don't do anything really bothers me too, because they are a misconception of how those complex architectures (Clean/Hexagonal/Onion) really work...
Instead of having mandatory layers, those should be pluggable. Just having a layer calling the next one is unnecessary, and some people implement it by having the next layer as a transitive dependency, which makes testing harder and has zero benefits!
> The thing about the multiple "layers" that don't do anything really bothers me too, because they are a misconception of how those complex architectures (Clean/Hexagonal/Onion) really work...
> Instead of having mandatory layers...
C# guy here.
I don't think things were ever as bad in the dotnet world as they are in Java, but l do still come across a lot of what you're describing here. Thankfully though, a lot of devs do seem to have "awakened" - it feels like there is a lot less cargo-culting of "best practises" such as layers, interfaces and abstract classes for everything, tests so full of mocks you can't see anything being tested etc.
C# is a fantastic language, but as with any OO language there are lots of abstraction-related traps to fall into.
For me, Java’s ties with Oracle and the nightmare stories about complicated `MetaAbstractBaseClassFactoryClassFactory` are why I seek alternatives, or would be dismissive.
Just noting that the abstraction stuff is mostly a consequence of the CORBA-derived, over-engineered "Enterprise Java" space, and provided you stay out of that tar-pit, and choose your libraries/dependencies wisely, Java is really nice to work with.
Even if you need to implement some kind of "Enterprise Java" app, you can do so with much better libraries and tools than back then, that do not suffer from the excessive abstraction problem.
My first programming job was a pilot study for porting a platform from old and busted CORBA to the new hotness, J2EE. It was embarrassing how much worse than CORBA J2EE was.
I still see factories on a daily basis. They are a useful design pattern that is utilized in Java.
My anecdotal evidence is that I have never seen the over-engineered "Enterprise Java horrors" OP is talking about despite working in the Java EE (now Jakarta EE) space.
I suspect it's a story from the times of J2EE, or something similar.
> I still see factories on a daily basis. They are a useful design pattern that is utilized in Java.
A separate factory type means you have to write twice as much code for no real benefit. In most languages you'd just use a first-class function (and in post-8 Java you can do the same: rather than a FooFactory you accept a Supplier<Foo> and people can pass ::Foo . It's still more cumbersome than in most languages though). Or, in a lot of other cases, the factory is just a clunky way to achieve named arguments.
> My anecdotal evidence is that I have never seen the over-engineered "Enterprise Java horrors" OP is talking about despite working in the Java EE (now Jakarta EE) space.
Have you worked on a reputable codebase in a low-overhead language like Python or Ruby? If you don't recognise factories as bloat then you may well miss the other cases (famously, the majority of the Gang of Four patterns can just be replaced by passing a function).
> A separate factory type means you have to write twice as much code for no real benefit.
Ah! There's the confusion. What I meant was I see factory methods in code we consume on a daily basis, not that we write the full factory objects. A number of Java projects have static factory methods that provide the interface implementation instance based on your configuration.
If you're actually using that configurability (i.e. your method actually instantiates different implementations in different cases) then no - that's the same thing you'd do in any language. If you're pre-emptively defining factory methods that actually just call the normal constructor then yes (a lot of Java bloat is like that - see also getters and setters on every field for the sake of the 0.01% where you actually want to do something other than just read/write the field).
It's not Javas fault it got bought by Oracle (and I don't agree that is is bad, as Oracle advanced it quite).
And I do like 'MetaAbstractBaseClassFactoryClassFactory' type names because that allows me in an application with hundreds if not thousands of classes to find the class I'm looking for very fast by just typing a few keywords into my IDE.
> Out of curiosity, as a Java enthusiast, I was wondering if you could give examples of what you feel is wrong?
I think there's a lot of criticism for Java's language design. It involves an awful lot of boiler plate, and is generally very verbose. It's also a language that forces you to use OO, and OO has received a lot of pushback over recent years - so that approach has become very unpopular.
Personally, I also think the use of so many design patterns is an attempt to compensate for what the language lacks, its reflection capabilities are flawed etc.
I don't hate on Java. For many years it was my main language. It has awesome tooling and the JVM is incredible. But I do agree with most of the criticism.
I've been learning Clojure recently and Rich Hickey's talks often begin with some motivation including criticism of Java and OO more generally, here's one such video: https://www.youtube.com/watch?v=VSdnJDO-xdg
> In my HN browsing I find Java is rarely actually discussed here, though often dismissed. I don't know why.
Personally, I feel like Java is not really as hated as some people make it out to be. It's a stable language that very few people choose for their "cool side project". At the same time, it has excellent tooling, mature and prod-ready open source frameworks, and backing of some giant companies.
This is not to say that Java is perfect. I think most dissatisfaction comes from students or junior people who are baffled by the complexity of Maven/Gradle configurations, strict project structure (where a class can be 10 directories deep), and Java's insistence on boilerplate (which is often challenged by new Java releases. Those, however, are quite rare in production; I'm starting to see Java 11 here and there but the majority of projects I've seen run 1.8).
Out of curiosity, as a Java enthusiast, I was wondering if you could give examples of what you feel is wrong?
In my HN browsing I find Java is rarely actually discussed here, though often dismissed. I don't know why.