Replacing Utility Classes With Interfaces And Java 8

Utility classes act a a bag of related static methods with a private constructor:


package java.lang;

public final class Math {

    /**
     * Don't let anyone instantiate this class.
     */
    private Math() {}

    public static double sin(double a) { /**/}

Java 8 introduces a leaner alternative -- the "utility interface" and makes the private anti-constructor superfluous:


public interface Math {
    public static double sin(double a) { /**/}
}

See e.g. Contexts.java from the nano project.

See you at Java EE Workshops at Munich Airport, Terminal 2 or Virtual Dedicated Workshops / consulting. Is Munich's airport too far? Learn from home: airhacks.io.

Comments:

While I do like the pragmatic approach I think it can be missused. The purpose of an interface is to define a contract that can be implemented and not to serve as an utility class. If the intention is clear for the team, than it is ok.

Posted by Carlos on December 21, 2015 at 05:02 PM CET #

Thanks for pointing out this leaner possibility. Getting rid of the anti-constructor is helpful, indeed.

The new approach can come with a drawback, though: you cannot have private static methods or fields in an interface, which might be useful in some (bigger) utility classes.

Posted by Uwe on December 21, 2015 at 08:23 PM CET #

Nice tip. Thank you!

Posted by Romeo Frenksen on December 21, 2015 at 09:15 PM CET #

I don't like this as it may lead to more and more logic creep into interfaces. Default methods were introduced to change interfaces while keeping backwards compatibility (as for example for the lambda expressions):

"Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces." (source: https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html)

I don't like to see default methods being used for other purposes than this. For example I know developers who think it's a flaw of Java that it doesn't have multi-inheritance. My hope is that those guys won't understand that they have multi-inheritance now. Else they will use default methods for things which they were not introduced for.

Your "utility interface" is a very pragmatic approach (which I like) but it has another drawback: How do you prevent the interface from being implemented? The class-approach clearly states that it is final and it don't wants to be instantiated.

Posted by Kai on December 21, 2015 at 09:52 PM CET #

I agree with the comments above: the concept of Interface is not respected when used like that.
And all this missuse to save up one line of code ?
Coding inside an interface... I really didn't expect that from Java. Thank god this Default Method was not intended to it.

Posted by Mauricio on December 22, 2015 at 08:45 PM CET #

Good tip! Note that you can also avoid the private constructor by marking the class as abstract, which IMHO is better because it allows to define private methods that support the public ones.

Posted by Esala on January 10, 2016 at 10:52 PM CET #

This blog suggestion doesn't seem as a good practice to me. Letting interfaces having method implementation wasn't a supposed feature but kind of compulsion due to backward compatibility to support lambda in collections. So, lets interface be an interface :)

Posted by Sunny on August 27, 2018 at 04:48 AM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
...the last 150 posts
...the last 10 comments
License