Beauty or Beast - I'm not sure which

I recently came across the following bit of strangeness: in Java, an interface cannot have static methods; however, an interface can have public static classes, which themselves can have static methods. Which in effect allows you to put static methods on an interface, like so1:

interface Thinger{
    public static class util{
        public Thinger parse(InputStream in){ ... }
        public void serialize(Thinger thinger, OutputStream out) { ... }

    public Thing doSomething();

"Why on earth do you want to put static methods on an interface?" you might ask. Essentially, static methods on an interface would allow the interface designers to provide utilities that do useful things with implementors of the interface without having to create a separate utility class, or worse toss the desired functions into an existing utility class.

I'm somewhat torn on whether this is a particularly good or a particularly bad idea. On the one hand, implementing generic algorithms in terms of interfaces is a truly handy thing to do and providing those implementations close to the interface definition seems to be helpful. Furthermore, creating interface specific utility classes helps to avoid the creation of monstrous Util classes whose cohesion can be summarized as "code other code uses". On the other hand, the designers of the language obviously didn't want actual code injected into interfaces, after all static methods are prohibited on interfaces. As such, I'm undecided. This is either really awesome or really awful.

Collections API: A Case for Utility Classes on Interfaces

Case-in-point, the collections API2 includes a class named Collections whose sole purpose is to provide interesting and useful methods to implementers of Map, List, Set, Collection and others.


Hierarcy of the classes in the collections API. Shown are the principle interfaces and the Collections utility class.


Dependency graph of the collections API. Notice how the Collections class couples together List, Set and Map without any real reason.

Collections is a large and complicated class with 53 methods (as of Java 6.0) with little cohesion. The class could arguably be decomposed into interface specific utility classes like so:

interface Collection<E>{
    public static class util {t
        static <T> Collection<T> synchronizedCollection(Collection<T> c){ ... }
        static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c){ ... }

    boolean add(E e);

interface List<E>{
    public static class util {
        static <T> List<T> synchronizedList(List<T> list){ ... }
        static <T> List<T> unmodifiableList(List<? extends T> list){ ... }

    boolean add(E e);

By providing implementation of the utility methods directly in the interface definition we eliminate the need for the Collections class entierly, and improve the cohesion of the utility methods that are collected together in structure specific utility classes.

We can see that not only does this remove the need for the Collections class, but it also removes the unnecessary dependencies that Collections introduced. Whether that's a compelling enough reason to be a little fast and loose with the definition of interface is up to you.


For those of you that have made it this far, I'd just like say that the diagrams prepared for this post were created using the Violet UML Editor which is the most pleasant UML editor I've ever used. It is not a CASE tool and it doesn't support sub-states in state diagrams3, but for the most part when you're drawing it Does-The-Right-Thing (TM) and the diagrams look pretty good. So the next time you feel like drawing a class diagram (I can't be the only one who ever feels that way) give it a shot, I think you'll be pleasantly surprised.

[1]Yes I know that naming the class 'util' violates naming conventions and makes it look like a field: that's the idea.
[2]The set of classes that provide implementations of generic data structures that are essentially indespensible in writing interesting programs.
[3]I should really contribute a patch rather than continually complaining about this.