While there are a huge number of wonderful things about the Java API it has some examples of truly terrible API design. You can probably find that somewhere it breaks every rule in the "Effective Java" book (for sale on amazon.com and amazon.co.uk, and cheaper in the UK than the US for a change).
One example is the java.util.Properties. A properties object is supposed to be a set of keys and values (like a map) where the key and value are both strings. The problem is it extends Hashtable which means you can pass it to anything that takes a Dictionary, or Hashtable. While this may seem useful it means that you can use non-string values. This can cause problems if the getProperty method is later used.
This kind of problem is inevitable because API design is so hard. So what can we do to "fix" things in the future? There are (at least) two ways to cope:
- Maintain the API forever. This is probably the most common solution. Java is full of old, deprecated, or discouraged APIs. Hashtable, Dictionary and Vector have been replaced with Map, HashMap, List and ArrayList, most of the Date class has been deprecated.
The problem with this approach is that people often still use these older APIs, even though there are better alternatives.
- Version the API. A non software example of what I am thinking of the PS2 contained the old PS chip as an I/O controller and the PS games were run on that.
Java does not support versioning itself, but can be supported by making use of OSGi. OSGi is a modularity system that is built on top of Java. OSGi is split into a core and a set of optional services. The core is implemented by Eclipse Equinox, Apache Felix among others. Running an application inside of OSGi allows you to provide two different, and incompatible versions of the API in the same JVM and allow the user to select the version they work with.