The many frameworks designed to simplify the Java development experience do make experienced Java developers more productive, but make the learning curve too steep for those new to Java.
Compile-time checking of exception and types adds safety, but comes at a cost of additional time and syntax.
Java's inability to express structured data leads to an over-reliance on XML, with the corresponding additional complexity and bloat.
Java's many compromises, like primitives, make Java harder to learn and more complex to write.
Java is more dynamic than C++, but is nowhere near as dynamic as languages like Smalltalk and Ruby. Java developers are finding metaprogramming, but they're not able to execute on those ideas fast enough.
Java's long compile/deploy cycle is much longer than interpreted, dynamic alternatives.
Taken alone, none of these issues hurts enough to matter. Taken together, Java becomes much less productive for most developers.
Steve Yegge: Java's Limitations
Language expert and creator of Wyvern
Steve Yegge, a graduate of the University of Washington, spent five years as an Assembly-language programmer at Geoworks and more than six years as a software development manager at
Amazon.com. Steve somehow managed to find time to design, implement, and maintain a massive multiplayer game called Wyvern (
http://www.cabochon.com/), with a half-million lines of Java and Python code.
What is your experience with Java?
SY: I was a card-carrying member of the Java community from late 1996 through mid-2003. I used Java to build a cool, multiplayer, user-extensible online game. Java got me really far, and I loved it for seven years.
Why did you start looking at other languages?
SY: I simply hit a productivity wall. As my code base grew, my innovation slowed, until finally, tasks were taking me an order of magnitude longer than I felt they should. I stopped development for six months and did a deep-dive investigation to figure out what the heck was going wrong. It wasn't what I expected. The problem was Java. I was pretty unhappy about this. I'd invested an awful lot in Java. AOP helped a little (albeit at a high entry cost), but nowhere near enough. Nothing else helped at all. What I needed was a new language.
How does Java hold you back?
SY: First, Java offers an impoverished set of abstractions. No first-class functions, no reference parameters, no keyword or default params, no destructuring bind or even parallel assignment, no way to return multiple values efficiently, no continuations, no user-defined operators, no generators, no closures, no tuples...the list just goes on. Java's about 25 teeth shy of a full mouth.
Second, Java is entirely nonextensible. It can't grow. There's no metaprogramming, no macros, no templates, nothing that gives you syntactic abstraction. So, Java's incompressible. Java code is always filled with stuff that looks like copy and paste, but you can't factor it out. Java code and APIs always wind up bloated (and yet oddly impressive looking).
Third, Java can express code, but not data. You're stuck using property files, XML, and other means of defining data. But the line between code and data is blurrythink about configuration, for example. So, the Java folks are piling on framework after framework, creating this huge pipeline of transformations that can't be expressed in Java.
Fourth, Java's static type system sucks. Actually, all static type systems suck, but Java's is worse than most. It gives you only narrow avenues along which you're permitted to think. Java programmers must painstakingly learn to pound star-shaped pegs into square holes; this is what design patterns are mostly about.
Fifth, Java has far too much nonessential complexity. For instance, it now has four kinds of types: primitives, classes, arrays, and enums. All the type types have their own syntax and semantics, which you must learn and then handle in your APIs. It's not just types, either. Java's entire syntax is large and bureaucratic. Java's syntax is complex for no good reason.