28

For the past decade or so, I've been using the pattern below for my Java utility classes. The class contains only static methods and fields, is declared final so it can't be extended, and has a private constructor so it can't be instantiated.

public final class SomeUtilityClass {
    public static final String SOME_CONSTANT = "Some constant";

    private SomeUtilityClass() {}

    public static Object someUtilityMethod(Object someParameter) {
        /* ... */

        return null;
    }
}

Now, with the introduction of static methods in interfaces in Java 8, I lately find myself using a utility interface pattern:

public interface SomeUtilityInterface {
    String SOME_CONSTANT = "Some constant";

    static Object someUtilityMethod(Object someParameter) {
        /* ... */

        return null;
    }
}

This allows me to get rid of the constructor, and a lot of keywords (public, static, final) that are implicit in interfaces.

Are there any downsides to this approach? Are there any benefits to using a utility class over a utility interface?

Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
  • If you make it an interface, people are inevitably going to `implement` the interface to avoid typing `SomeUtilityInterface.`, because they don't know how to do a static import or don't want to. – user2357112 Jun 18 '15 at 01:55
  • @user2357112 I don't believe `static` methods from interfaces are inherited. You still need a qualified invocation. – Sotirios Delimanolis Jun 18 '15 at 02:02
  • @SotiriosDelimanolis: They'll get the constants, though, and that'll be enough to make people do it. – user2357112 Jun 18 '15 at 02:04
  • @user2357112 Is that bad? – Sotirios Delimanolis Jun 18 '15 at 02:06
  • @SotiriosDelimanolis Yes, it's bad: http://www.javapractices.com/topic/TopicAction.do?Id=32 – Brett Kail Jun 18 '15 at 02:09
  • I believe this falls under the same anti-pattern category as using an interface for constants: "*since constants are very often merely an implementation detail, and the interfaces implemented by a class are part of its exported API, this practice amounts to putting implementations details into the API*" You are mixing implementation details with the API – Vince Jun 18 '15 at 02:09
  • 1
    @SotiriosDelimanolis: It puts the implementation details of a class into the class's public API. I believe one of the specific reasons static imports exist is to make people less inclined to do it. The [Oracle documentation on static imports](http://docs.oracle.com/javase/8/docs/technotes/guides/language/static-import.html) specifically calls out the Constant Interface Antipattern as a really bad idea. – user2357112 Jun 18 '15 at 02:11
  • @VinceEmigh There's a difference between declaring a *Constant Interface* and actually implementing it. I wholeheartedly agree that implementing it is a bad idea. About declaring it and just using the constants in `static import`s, I'm not so sure. It seems that the *Constant Interface Anti-Pattern* refers to the former. – Robby Cornelissen Jun 18 '15 at 02:17
  • 1
    I'm not fully convinced yet...if the interface doesn't expose any abstract methods. But it actually doesn't really matter since those methods aren't inherited. I wouldn't really care to go through all that for just the fields. – Sotirios Delimanolis Jun 18 '15 at 02:17
  • 2
    As the man himself (Joshua Bloch; guy who coined the constant interface an anti-pattern): "An API should be easy to use and *hard to misuse*. It should be easy to do simple things; possible to do complex things; **and impossible, or at least difficult, to do wrong things**". With my experiences with the few mainstream APIs that use a constant interface (such as ASM), I've always found it easier to implement an interface (Opcodes from ASM) than write a static import. I guess it depends on how strict on design you are – Vince Jun 18 '15 at 02:51
  • 1
    @Vince Emigh: it rather depends on how good you are in using/ configuring your IDE. In the best case, the IDE will automatically suggest you the constants and insert `import static` when necessary, but it will never suggest you to `implement` an `interface` that is not actually used as a real type (there is no heuristic hinting the IDE in that direction). – Holger Jun 18 '15 at 08:03
  • 1
    @Robby Cornelissen: Your initial premise is wrong, you don’t save anything. E.g. you say “This allows me to get rid of the constructor” but, of course, you could omit the `private` constructor of the utility `class` as well, to the same result. You *don’t have* a `private` constructor, in both cases. The only type where you can omit the constructor and will get a `private` constructor is an `enum`. But abusing a `enum` without constants for a utility class would imply having two additional compiler generated useless `public static` methods in your API. – Holger Jun 18 '15 at 08:09
  • 1
    @Holger I don't need nor want a constructor, but If I omit the private constructor declaration, I will end up with the default public constructor, thus allowing the class to be instantiated. With an interface this is not the case (but I can't prevent it from being implemented by classes, anonymous or other). I never suggested using an `enum` as a utility class. I already abuse those for my singletons (in the rarest of cases). – Robby Cornelissen Jun 18 '15 at 08:37
  • 1
    @Robby Cornelissen: that’s exactly the point, if you omit the private constructor declaration, you will end up with the default public constructor, thus allowing the class to be instantiated. With an interface *you don’t get any benefit* as you can’t prevent implementation of the interface at all. So abusing an `interface` doesn’t allow you to omit the constructor declaration, it *doesn’t support* a `private` constructor. And I didn’t say that you suggested using an `enum` as a utility class, **I** emphasized that using an `enum` would be actually the better choice but still having drawbacks… – Holger Jun 18 '15 at 08:52
  • @Holger I think we're in agreement, but in my argumentation I distinguish between instantiation and implementation. I can prevent my class from being instantiated by declaring a `private` constructor, while the interface cannot be instantiated by design. I can prevent my class from being implemented (extended) by declaring it `final`, but I cannot prevent my interface from being implemented/extended. Apart from code clarity, violation of the principle of least astonishment, etc., this indeed seems to be the biggest weakness of this utility interface pattern. – Robby Cornelissen Jun 18 '15 at 09:08
  • 2
    Note that you can prevent arbitrary implementations of an `interface` by adding an abstract method containing references to non-`public` types in its signature. Then, implementations outside the package are impossible. Nevertheless, that wouldn’t raise clarity as the abstract method would appear in the `public` API and developers would start wondering about the purpose of that method and when discovering by trying the impossibility of implementing the interface, they would think that there must be a mistake. – Holger Jun 18 '15 at 09:13
  • 1
    Yep, this is an abuse. You're using the wrong abstraction just to save typing a few keywords like `final` or `public`. Remember the #1 rule: _reading code is more important than writing code_. Readers will be (legtimately) confused that somehow your SomeUtilityInterface represents a type that means something. Distorting your code to save typing is always wrong. – Brian Goetz Jun 18 '15 at 11:49

4 Answers4

11

You should use interface only if you expect that somebody would implement it. For example, java.util.stream.Stream interface has a bunch of static methods which could be located in some Streams or StreamUtils class prior to Java 8. However it's a valid interface which has non-static methods as well and can be implemented. The java.util.Comparable is another example: all static methods there just support the interface. You cannot forbid users from implementing your public interface, but for utility class you can forbid them to instantiate it. Thus for the code clarity I suggest not to use interfaces unless they are intended to be implemented.

A note regarding @saka1029 answer. While it's true that you cannot define helper private methods and constants in the same interface, it's not a problem to create a package-private class in the same package like MyInterfaceHelper which will have all the necessary implementation-related stuff. In general package-private classes are good to hide your implementation details from the outer world.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
  • I also think that code clarity is indeed a valid concern. – Robby Cornelissen Jun 18 '15 at 02:46
  • 1
    As a side note, Java 9 allows `private` methods in `interface`s, so it’s a good thing that your answer doesn’t depend on the absence of that feature, but will remain valid even then. – Holger Jun 18 '15 at 08:26
  • 1
    Java 9 should introduce private methods http://openjdk.java.net/jeps/213 – assylias Jun 18 '15 at 08:26
  • 1
    @Holger haha - you beat me by 12 seconds, 5 hours after the post... I wonder what the probability of that happening is :-) – assylias Jun 18 '15 at 08:27
  • 1
    @assylias: and I tried it first with a jdk snapshot. So the time to write a little interface and the run javac determined the time I sent the comment… – Holger Jun 18 '15 at 08:32
5

Going based on the person who coined the Constant Interface pattern an anti-pattern, I would say although you don't intend the client(s) to implement the interface, it's still possible, possibly easier, and shouldn't be allowed:

APIs should be easy to use and hard to misuse. It should be easy to do simple things; possible to do complex things; and impossible, or at least difficult, to do wrong things.

Although as mentioned below, it really depends on the target audience


A lot of easy-to-use designs patterns get a lot of criticism (Context pattern, Singleton pattern, Constant Interface pattern). Heck, even design principles such as the law of demeter gets criticised for being too verbose.

I'd hate to say it, but these kinds of decisions are opinion based. Although the context pattern is seen as an anti-pattern, it's apparent in mainstream frameworks such as Spring and the Android SDK. It boils down to the environment, as well as target audience.

The main downside that I can find is listed as the third listing under "downsides" in the Constant Interface wiki:

If binary code compatibility is required in future releases, the constants interface must remain forever an interface (it cannot be converted into a class), even though it has not been used as an interface in the conventional sense.

If you ever figure "Hey, this actually isn't a contract and I want to enforce stronger design", you will not be able to change it. But as I've said, it's up to you; maybe you won't care to change it in the future.

On top of that, code clarity as mentioned by @TagirValeev. Interfaces have the intent of being implemented; if you don't want someone to implement the API you're supplying, don't make it implementable. But I believe this revolves around the "target audience" statement. Not gonna lie, I'm with you on the less-verbose foundation, but it depends on who my code is for; wouldn't wanna use a constant interface for code that may get reviewed.

Vince
  • 14,470
  • 7
  • 39
  • 84
2

You should not use interface. Interfaces cannot have private constants and static initializers.

public class Utility {

    private Utility() {}

    public static final Map<String, Integer> MAP_CONSTANT;
    static {
        Map<String, Integer> map = new HashMap<>();
        map.put("zero", 0);
        map.put("one", 1);
        map.put("three", 3);
        MAP_CONSTANT = Collections.unmodifiableMap(map);
    }

    private static String PRIVATE_CONSTANT = "Hello, ";

    public static String hello(String name) {
        return PRIVATE_CONSTANT + name;
    }
}
  • 2
    Shouldn't have global mutable state in the first place (the reason why Singleton is an antipattern). I don't feel this is a good enough reason – Vince Jun 18 '15 at 02:45
1

I think it would work. I think the variable SOME_CONSTANT defaults to being static final in your SomeUtilityInterface, even though you didn't explicitly say so. So, it would work as a Utility but wouldn't you have some mutability problems that you wouldn't have with a regular class with all member variables being required to be final? As long as thats not an issue with your particular implementation of the default methods, I can't think of a problem.

djangofan
  • 28,471
  • 61
  • 196
  • 289
  • 1
    It definitely works. And the interface fields are implicitly `public`, `static` and `final`, so I don't think there are any mutability problems. – Robby Cornelissen Jun 18 '15 at 02:04
  • Normally final members can only be modified in the constructor right (not in a containing method)? And so, maybe they can be set in the constructor of the implementing class? Have you tried that? – djangofan Jun 18 '15 at 02:07
  • 1
    Final members can be initialized in the declaration or the constructor, but they can only be initialized once. Since the fields in the interface are `public static final` by default, and they have been initialized on declaration, I don't see how what you describe can be done. – Robby Cornelissen Jun 18 '15 at 02:10
  • Yeah, I am thinking is not a good idea. I usually auto-wire utility classes and instance members with Spring and so really it works well to do it as a regular class. – djangofan Jun 18 '15 at 02:27