I'm more at the novice end of the software developer spectrum, but nevertheless I've had exposure to quite a few programming languages and frameworks. From all the technologies I've used, I haven't found any with an API as well-structured and user-friendly as Java's. Why is this? Why is it that robust languages such as C++, Perl and Python do not have APIs that come even close to Java's?
Your opinion might change as you get more experience with other languages. I have found the Java APIs to be rather poor:
Date and Calendar and related classes are a mess.
The collection classes are unwieldy, and don't play well with arrays. This is a problem because some methods return collections while other methods demand arrays. Very common Collection operations are missing. I found the C++ standard template collections to be more powerful, and more easily extensible.
The standard Java libraries support String split, but still do not support String join, which is available in almost every other language.
- Java I/O is inconvenient when compared to languages that allow streams to be processed as collections.
- The Java Reflection API is also quite unwieldy, but that may be more a function of the Java language design.
- There are far too many classes that have separate methods for passing objects of various types, e.g. setDate, setInt, setString, instead of set(Object).
- Other languages (Perl, Python, Ruby) have a common module repository. Java does not.
I'm curious to what you think of C# / .NET's api, btw, as far as I know it's on-par if not better than Java's. (Unbiased, I'm a Java guy myself)
As to your question, I have a few theories. The C++ libraries are built out of the old C library and the STL on top of that. Back when, it was one of the earliest standard libraries, and one of the first object-oriented programming languages (preceded by Smalltalk and probably a few others - I'm not too familiar with OO language history). This means not too much experiences yet, amongst other things.
What makes Java's (and .NET's) APIs / libraries / documentation better are two things:
- Corporate support
Experience in that they were able to start with a clean slate at the time - no backwards compatibility with existing libraries required, so they could built a standard library that was based on the best ideas of the past, and then some. Of course, the actual quality of the API's / standard libraries has deteriorated some, mainly due to having to maintain backwards compatibility (example is the old Collection classes like Vector and Hashtable, which have been superseded by List and Map but are still in the API for the sake of backwards compatibility).
Corporate support is very important here, as this meant there was a team of people that could spend their whole working day writing the library and documentation. This is contrary to the languages / libraries without corporate support, which rely on volunteers and a community.
I'm pretty sure it's a matter of culture, too. Java (and .NET, too) are both very 'corporate'- high security, backwards compatibility, etc. Python and Lisp and such on the other hand are more aimed at the 'hacker' community (to generalize, I can't think of a better word). You don't see much Java in the *Nix world (and no .NET worth mentioning, for that matter), but a huge amount of Python, Lisp, and what-have-you.
Java was written as a blue-collar programming language for professional programmers. (Which is why teaching Java to students is inappropriate)
Go look at the original Java stuff by James Gosling.
So it's got ugly bits in the libraries ( you get used to them and eventually they get fixed)
But it's also got a long history of conservative software engineering that doesn't break my million lines of code just to add gee-whiz language or library features. I don't want to assign resources to fixing version migration. There is no competitive advantage for me there.
Contrast with C#'s approach to generics, where you get a new collection library.
This conservative approach makes it hard to change library objects that are badly designed, but some progress is being made on that.
So a bit more time gets spent on polishing the documentation. And we get where we are today.
The commitment the Java team has made to avoid introducing non-backwards compatible changes means that they probably think long and hard when they're extending their API, instead of just throwing something out there. Compare this to (say) PHP, which completely changed the handling of XML in PHP5 - no deprecation, just gone.
The reasons are historical and philosophical, with the history deeply affecting the philosophy.
C++, Perl, and even Python are all older then Java, and because of Moore's law they were developed in an environment where disk and memory were one or two orders of magnitude more expensive. Developers very much wanted to pick and choose which APIs they had on a system because memory and disk were expensive, and networks were slow. Why not let developers exercise their judgment and chose whatever library they thought best?
Java was originally developed for proprietary, embedded software so it HAD to provide all the libraries used at run time. When Java migrated to general purpose computing this turned out to work pretty well for folks doing line-of-business software, but it was also one of the reasons why Java initially got smacked as being slow and bloated.
If you go to a nice restaurant you'll often be given a choice between "prix fixe" and "ala carte". Each course of the prix fixe meal, and maybe even the wine is chosen by the chef in advance. This is great if you don't know much about the food and trust the chef. If you have very particular tastes or think the chef is a moron, you'll want to order ala carte, where you pick each course to exactly suite your taste.