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!)
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.
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.
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#.
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.