A couple days ago, I was trying to figure out how Java's cryptography packages work. I quickly came to the conclusion that they are an absolute horrible, horrible mess - just like everything else in the standard library. For example, while converting an RSA public key to a byte array is as simple as:
byte publicKeyByteArray = publicKey.getEncoded();
... getting the byte array back into a public key object is:
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyByteArray));
The real problem, though, is the abundance of objects for doing things that shouldn't need objects. Want to encrypt or decrypt a message? Use a Cipher object. Want to hash a string? Use a MessageDigest object. Doesn't seem so bad, right? After all, it has some nice applications for polymorphism (e.g. who cares if it's SHA-1 or SHA-256, it works the same). But after a while, it starts to get ridiculous. Want to generate a symmetric key? Use a KeyGenerator object. What about an asymmetric key pair? Grab a KeyPairGenerator object. Want to convert a byte array to Base64 and back? You need not one but two objects: a BASE64Encoder and a BASE64Decoder. And for some reason, decoding (but not encoding) a Base64 string can throw an IOException. God only knows why.
And, of course, those two Base64 classes are in the unsupported sun.* hierarchy, meaning they could change from platform to platform and even between releases. If you want to actually guarantee that your code will work, you have to write your own Base64 implementation.
This is not an isolated problem. Every part of the standard library is like this. And thanks in part to the standards recommended by Sun, most Java APIs written by other people are a mess as well. Combined with the absence of syntactic sugar that other languages consider essential, like properties and function references, Java code can quickly become a bureaucratic disaster.
Where did Java go wrong? Before Python and Ruby came along, Java was the language of choice (read: maximum hype). Now no one believes that Java is a practical language for some of the applications for which it was originally designed, such as applets.
So, Slashdot: what can we learn from the failure of Java?