Monthly Archives: October 2013

Defining constants in an interface

Effective Java says in Item 19, that “Use interfaces only to define types”. This time I would like to argue with this statement, but before starting a debate lets see the reasoning of that short chapter. What is the ground for the advice that diverts us from defining constants in interfaces. (Constants I mean public static final variables.)

The constant interface pattern says that

  1. you define the constants in an interface, and
  2. the classes needing the constants implement the interface.

This way the constants can be used as they were defined inside the class. The interface and thus the constants defined in it became part of the class. This is easy and convenient. What is the problem?

The problem is that the interface does not only become part of the implementation of the class but it also becomes part of the definition of the class. A class has tangible part that you face every day as a programmer: this is the implementation. The intangible part is the definition of the class: what it is for. Since you can define and use a class without implementing any interface the definition of a class may be implicit. If there are no interfaces that the class implement, or even if the class implements some interfaces the definition of the class lies in the documentation of the class, in the signature of the accessible methods and generally in common sense.

When a class implements an interface the interface becomes part of the definition of the class.

The constant interface pattern is a poor use of interfaces.

The before-mentioned book says “implementing a constant interface causes the implementation detail leak into the class’s exported API”. Later on the book draws the conclusion “In summary, interfaces should be used only to define types. They should not be used to export constants.”

And now the debate:

Drawing this conclusion is too bald, in my opinion. The pattern contains two steps: 1. defining constants in interface, 2. implementing the interface. The conclusion focuses on the first step of the pattern. Of course if you avoid step 1 you can not do number 2. But the problem is actually not the interface defining constants. The problem is that the class is implementing the interface.

The book suggests to use utility classes to define constants. However interfaces could be used exactly the same way as utility classes defining only constants. There is no even syntactic difference in the use. You import the class/interface, you can do static import if that fits your personal/corporate style and you use the constants defined in the class/interface. The major difference is that the interface can not be instantiated by its nature while utility classes can. Utility classes should have a private constructor to avoid accidental instantiation. In an interface all variables are public static final by default. In utility classes you have to define them to be like that, which leads to code clutter. Using an interface you may not accidentally forget the final, public or static because they “are there” by default. Checkstyle even warns you not to use those keywords in an interface. The compiler knows it anyway and the person who reads the code to maintain it is supposed to know Java.

What is the drawback of defining constants in an interface then? It may accidentally be implemented and this is against the nature of an interface to deliver implementation. While I can not argue with the first part of the statement the nature of interfaces are not that solid. What about Java8? There can be static methods in an interface, and default method implementations. You may like it or not but the direction Java currently goes with interfaces is more towards the practical way. Using a pattern that defines constants in an interface to import it instead of “implementing” is directly this way.

As a summary, my suggestion is to avoid using the interface pattern as defined in “Effective Java”. Never implement an interface in any of your classes only to get access to the constants defined in the class, unless the constants are inherent part of the definition of the class and not only the part of the implementation. On the other hand I see no significant danger to define a constants only interface and import it into your class and use the constants.

Next week I will write about an extended pattern using interfaces to define constants that avoids the possibility to accidentally “implement” them.

Advertisement

Do not return from ‘try’ block

The document JPS_Coding_Standard_java R43 suggest that you do not abruptly exit a finally block. This means returning from it, throwing exception. The document lists two examples that are great, but then there are more things not to do:

Do not abruptly return from a try block!

Assume you have a try/finally construct and you return from the ‘try’ branch:

    StringBuilder stringed(final int a) {
        final StringBuilder b = new StringBuilder();
        try {
            b.append(a);
            return b;
        }
        finally {
            b.append(new StringBuilder().append(a).reverse());
        }
    }

What you actually should expect is to have a string builder returned containing the decimal representation of the int number a. However the finally branch modifies the object even before the method returns. Clean code says that there should be only one return statement in a method. Here we have only one, and still it is not clear what happens.

One may argue that the method works properly and it is supposed to return the string builder that contains the decimal representation of the number twice, once normal and once reversed and this is the way try and finally works. You may be a hard core old programmer who eats Java code for breakfast, but the code to be produced should always be targeting the average Java programmer, who will have trouble maintaining the code and understanding reading it is a must.

Better: never ever return from a try block. And just to try to impress you: the following is also a perfectly valid, and the same time perfectly mindless Java code:

    int $_() {
        $_: {
            try {
                return 1;
            }
            finally {
                break $_;
            }
        }
        return 0;
    }

If you can tell me the return value without hesitation and with total certainty, you are in the top 1% of the Java programmers. In that case you know the language more than needed and you wasted your time learning it to that level.