So, this is kind of a hard one.
Java’s got’s a lot going for it… the JVM is a pretty impressive piece of work, the runtime is pretty capable (and quite portable, for what that’s worth), and there’s a whole raft of third party libraries for all sorts of purposes. The language is quite mature and clearly isn’t about to go anywhere anytime soon, and there’s no shortage of folk out there who know how to code in it. It is interesting to note that there are many very powerful and quite ‘grown up’ open-source libraries and applications available in Java. Things like Hadoop, Eclipse and Open Office spring to mind.
The language stagnated somewhat whilst Sun was at the helm (you could argue that one man’s “stagnation” is another’s “stability”, of course) but Oracle seem to have stepped up their game somewhat: Java 8 even gets closures, so once again it has a pretty comparable set of features to C# and C++ (!). On the flip side, it suffers from all of the same complains I have about C# (not very surprising, really) plus a few more, like the fact that it inflicts a punishment upon its generics called “type erasure” upon its generics, so their generic nature is effectively invisible at runtime. This is of course quite expedient and makes implementing generics a fair bit easier, but the fact that dotnet has generics as first class citizens which support reflection shows that doing it properly isn’t just possible, but in some cases actually a benefit (but I won’t go into boxing issues here).
Have a read of this rant by Jamie Jawinski. It is practically ancient history now, but many of its most important parts still stand. I note he is still coding in C to this day… his observation that it is the only way to write portable code is sadly still very much the case.
That’s not the worst of it, of course.