Designing APIs With the Java 5 Language Features

DZone 's Guide to

Designing APIs With the Java 5 Language Features

· Java Zone ·
Free Resource

While implementing a mid-sized framework, I've discovered that the following Java 5 language features can help improve the usability of APIs.

  • Generics can help avoid casts in more ways than one, especially if instances of Class are used (see my blog post on this subject).
  • Generics and constructors: Generic constructors always need a type argument, while static methods (such as factory methods) can infer type arguments from their actual (method) parameters, leading to shorter code. This is an example:
    public class Foo<X> {
    public static <X> Foo<X> create(Class<X> elementClass) {
    return new Foo<X>(elementClass);
    public Foo(Class<X> elementClass) { }
    public X getElement() { return null; }
    public static void main(String[] args) {
    // Wrong type at right-hand side:
    Foo<String> foo1 = new Foo(String.class);
    // Proper way of doing it:
    Foo<String> foo2 = new Foo<String>(String.class);
    // Correctly infers the type:
    Foo<String> foo3 = Foo.create(String.class);
  • Interface Iterable enables the simplified for-each loops. This suggests that whenever you return an interface Iterator, you should also consider returning an interface Iterable. It is unfortunate that Java does not allow for-each to be applied to iterators. One can also use the following adapter:
    public class IterableWrapper<Elem> implements Iterable<Elem> {
    private Iterator<Elem> _iter;
    public IterableWrapper(Iterator<Elem> iter) {
    _iter = iter;
    public Iterator<Elem> iterator() {
    return _iter;
  • Varargs are good whenever the API asks for 0 or more "things". In the past, there were often two variants of a method, one with the optional argument (be it a list or an array), the other one without it. With varargs, you can unify both ways of invocation under one signature. Additionally, many data structures can be cleanly created with varargs, for example:
    public static final <T> Set<T> makeSet(T... elements) {
    return new HashSet<T>(Arrays.asList(elements));
  • Enums: Make it easy to discover the possible options for an argument. Compare this to the class SWT inside the Eclipse framework of the same name. Practically every GUI widget depends on the constants defined in this class, which makes looking up what constants apply in one particular case more difficult than it should be. Other advantages of Enums: Each enum constant is a full-blown object and one can perform all kinds of book keeping along with defining them; enums can be examined with a switch statement; the classes EnumSet and EnumMap provide memory-saving means for storing enums.
  • Interface Appendable: Unifies all objects “to which char sequences and values can be appended”. The list of implementing classes is long and includes StringWriter and StringBuffer. Consequence: Whenever you have an argument to which you want to "append" strings in a stream-like fashion, consider using this interface.


From http://2ality.blogspot.com/2010/10/designing-apis-with-java-5-language.html


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}