/ API DESIGN, INTERFACE, DEFAULT METHOD, JAVA 8

Default methods in Java 8, and what it changes in API design

Java 8 introduced default methods in interfaces. This post describes what they are, and how they can change the design of APIs.

A nominal design

Earlier, in Java, interfaces could only have contracts - method signatures with no implementation.

In order to add some implementation, a class was required, whether abstract or not.

Hence, traditional API design then followed this hierarchy:

nominal api design
  1. The root interface defines the contract
  2. An intermediate class implements common behavior i.e. Bar
  3. If necessary, a class in the hierarchy overrides this behavior e.g. Corge

A wrench in the works

This is perfect, until classes outside the reach of the API designer can implement the interface. The following hierarchy describes the List part of the Java Collections API, with an additional custom class:

collection api

Now, let’s introduce the sort() method in the List interface. Only classes i.e. AbstractList and MyList can actually implement this method.

Obviously, it’s impossible to enforce the same sort() implementation in both classes, even though it makes sense. Direct implementations of List have to duplicate (yuck!) the sort() of AbstractList.

In order to remove the duplication and DRY the design, Java API designers have moved the sort() method out of List to an unrelated class with only static methods.

collections

This resolves the common code issue, as there’s now only one single method responsible for sorting.

On the flip side, static methods are not object-oriented. Worse, there’s no relationship from List to Collections in the code (though there’s one in the opposite direction). Hence, if one is not aware of the Collections class and its features, there’s no way to know about it.

Default methods to the rescue

Now, imagine if it were possible to implement code in interface methods. The sort() method could be implemented in the List interface. The above class diagram would then look like that:

java8 collection api

That would solve the above issue. By default, every list implementation would be provided with the sort() method by inheritance.

This is exactly the reason for default methods. No more, no less.

For curious reader, the Collections.sort() implementation has been rewritten to delegate to the default method:

// Without generics for better readability
public class Collections {
    public static void sort(List list) {
        list.sort(null);
    }
}

Conclusion

If you end up having to duplicate code in multiple classes instead of factoring it into a single common interface, a default method is a far more elegant solution than helper classes.

Nicolas Fränkel

Nicolas Fränkel

Nicolas Fränkel is a Developer Advocate with 15+ years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with narrower interests like Software Quality, Build Processes and Rich Internet Applications. Currently working for Exoscale. Also double as a teacher in universities and higher education schools, a trainer and triples as a book author.

Read More