Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Designing APIs With the Java 5 Language Features

DZone's Guide to

Designing APIs With the Java 5 Language Features

· Java Zone ·
Free Resource

Build vs Buy a Data Quality Solution: Which is Best for You? Gain insights on a hybrid approach. Download white paper now!

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

Build vs Buy a Data Quality Solution: Which is Best for You? Maintaining high quality data is essential for operational efficiency, meaningful analytics and good long-term customer relationships. But, when dealing with multiple sources of data, data quality becomes complex, so you need to know when you should build a custom data quality tools effort over canned solutions. Download our whitepaper for more insights into a hybrid approach.

Topics:

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}