13

I've just recently noticed there is an option to have static methods in interfaces. Same as with static fields of interface, there is an interesting behavior: These are not inherited.

I'm unsure it's any useful in the actual interfaces that are to be implemented. However, it enables the programmer to create interfaces that are just envelopes for static stuff, like e.g. utility classes are.

A simple example is just an envelope for global constants. Compared to a class, you can easily notice the missing boilerplate of public static final as those are assumed (making it less verbose).

public interface Constants {
    String LOG_MESSAGE_FAILURE = "I took an arrow to the knee.";
    int DEFAULT_TIMEOUT_MS = 30;
}

You could also make something more complex, like this pseudo-enum of config keys.

public interface ConfigKeys {
    static createValues(ConfigKey<?>... values) {
        return Collections.unmodifiableSet(new HashSet(Arrays.asList(values)));
    }

    static ConfigKey<T> key(Class<T> clazz) {
        return new ConfigKey<>(clazz);
    }

    class ConfigKey<T> {
        private final Class<T> type;
        private ConfigKey(Class<T> type) {
            this.type = type;
        }
        private Class<T> getType() {
            return type;
        }
    }
}

import static ConfigKeys.*;
public interface MyAppConfigKeys {
    ConfigKey<Boolean> TEST_MODE = key(Boolean.class);
    ConfigKey<String> COMPANY_NAME = key(String.class);

    Set<ConfigKey<?>> VALUES = createValues(TEST_MODE, COMPANY_VALUE);

    static values() {
        return VALUES;
    }
}

You could also create some utility "class" this way. However, in utilities, it is often useful to use private or protected helper methods, which is not quite possible in classes.

I consider it a nice new feature, and especially the fact the static members aren't inherited is an interesting concept that was introduced to interfaces only.

I wonder if you can consider it a good practice. While code style and best practices aren't axiomatic and there is room for opinion, I think there are usually valid reasons backing the opinion.

I'm more interested in the reasons (not) to use patterns like these two.


Note that I don't intend to implement those interfaces. They are merely an envelope for their static content. I only intend to use the constants or methods and possibly use static import.

9
  • 1
    My knee jerk reaction to this is that it can only lead to bad things. Even though public static methods are essentially just namespaced global functions. It feels like allowing any implementation code in an Interface goes against its purpose as a contract definition absent implementation. I say leave partial implementation to Abstract classes. I will need to read up on why this was added.
    – Adrian
    Commented Dec 16, 2016 at 2:24
  • I have to go for now but I will write something up tomorrow on it. The short of it is that before an Interface had a clear purpose which was clearly separated from the purpose of an AbstractClass. Now they overlap heavily in a way that violates the language agnostic defintion of an Interface. Additionally there are cases where you can't inherit from multiple interfaces anymore if they implement default methods. So now there are exceptions to multiple interface inheritance where there didn't used to be any. Since Java has deviated drastically from the common defintion of an interface...
    – Adrian
    Commented Dec 16, 2016 at 11:11
  • it could also confuse new developers who are trying to get a proper handle on fundamental OOP concepts such as Interfaces, AbstractClases, when to use composition instead of inheritance, ...etc.
    – Adrian
    Commented Dec 16, 2016 at 11:13
  • Aliester, you are talking about default methods. I am talking about static methods and fields. Those aren't inherited, so they don't break the multiple inheritance.
    – Vlasec
    Commented Dec 16, 2016 at 11:23

5 Answers 5

1

A simple example is just an envelope for global constants.

Putting constants on interfaces is called the Constant Interface Antipattern since constants are often merely an implementation detail. Further drawbacks are summarized in the Wikipedia article on the Constant interface.

You could also create some utility "class" this way.

Indeed the Java doc states that static methods can make it easier to organize helper methods, for example when calling helper methods from default methods.

3
  • 1
    I don't think this actually is an Answer to the question posed since you could do both these things without this new functionality.
    – Adrian
    Commented Dec 16, 2016 at 10:43
  • Ah, so by the documentation, it's intended as a helper method. However, it is also public, which contradicts it. So maybe it is intended to also help the classes that implement the interface. But they are not inherited, so you'd have to use static import to make it feel like you inherited it. Well, thanks for looking it up in the docs.
    – Vlasec
    Commented Dec 16, 2016 at 11:32
  • 2
    There is absolutely nothing wrong with putting constants in interfaces, if those constants are somehow part of the API described by the interface. The only thing that is an antipattern is putting constants into interfaces without methods and having classes implement the interface only to refer to the constants without a class prefix. It's an abuse of interfaces and, since the introduction of static imports, completely obsolete. Commented Dec 16, 2016 at 19:13
1

As stated in the question, the interface is not meant to be implemented (or instantiated). So we could compare it with a class that has a private constructor:

  • The class can't be extended with no super() to call, but interface can be "implemented"
  • The class can't be instantiated without reflections, while the interface can be easily instantiated as an anonymous class as simple as this: new MyInterface() {};

This comparison is in favor of class as it allows more control. That said, class is not intended to be a holder of static stuff either, you'd expect it to have instances. Well, there is no perfect option.

There is also a weird thing about inheritance from the "static interface":

  • An "implementing" class inherits fields, but doesn't inherit static methods
  • An extending interface inherits no static members at all
  • (While a class extending a class inherits every non-private member ... and since it can't be extended by an interface, there is less room for confusion)

These might be reasons to consider it a bad pattern and keep using static classes for these cases. However, for someone addicted to syntactic sugar it may still be tempting even with the downsides.

1
  • ... Anyway, a team's coding conventions can cover those problems. To me, while it doesn't tie a programmer's hand nearly as tightly as a class with private constructor does, it still bears less risks than setters do, and setters are frequently used.
    – Vlasec
    Commented Dec 19, 2016 at 10:36
0

As @MarkusPscheidt this idea is essentially an extension of the Constant Interface antipattern. This approach was initially used widely to allow a single set of constants to be inherited by many disparate classes. The reason this ended being considered an antipattern was because of the issues that were encountered using this approach in real projects. I see no reason to think that these problems would only relate to constants.

Probably more importantly, there's really no need to do this. Use static imports instead and be explicit about what you are importing and from where.

4
  • Yes, static imports sound like a better idea than inheritance of constants and it works that works with static members of both classes and interfaces. And it is visible inside the class/interface only.
    – Vlasec
    Commented Dec 17, 2016 at 0:54
  • @Vlasec Right but there's no need to do this on an interface. The only difference between doing this with a class and an interface is that you can inherit from more than one interface. The standard practice for a utility class like this is to make the constructor private to prevent instantiation or extension. There's no benefit to doing this in an interface over a class. It simply opens the door for misuse.
    – JimmyJames
    Commented Dec 17, 2016 at 1:53
  • I can see value in constants on interfaces. Interfaces tend to define methods and methods sometimes accept constants as parameters. E.g: interface ColorFilter {Image applyGradient(int colorSpace, int width, byte[] pixels); }. I can imagine there being some different constants RGB, RGBA, CMYK, GREYSCALE, INDEXED etc. Commented Jan 7, 2017 at 22:45
  • @StijndeWitt This wouldn't be the worst thing but you can use an enum or nested class on the interface for this purpose. The real issue is using this to bring statics into the scope of many classes through inheritance. That approach is plainly inferior to using static imports.
    – JimmyJames
    Commented Jan 8, 2017 at 2:41
0

I would say, if you're interested in how to use the new feature properly, take a look at the code in the JDK. Default methods on interfaces are very widely used and easy to find, but static methods on interfaces seem to be very uncommon. Some examples include java.time.chrono.Chronology, java.util.Comparator, java.util.Map, and quite a few interfaces in java.util.function and java.util.stream.

Most of the examples I looked at involve uses of those APIs that are likely to be very common: conversion between different types in the time API, for example, for comparisons that are likely to be done frequently between objects passed to functions or objects contained in collections. My takeaway: if there's a part of your API that needs to be flexible, but you can cover say 80% of use cases with a handful of defaults, consider using static methods on your interfaces. Given how infrequently this feature seems to be used in the JDK, I would be very conservative when making use of it in my own code.

Your examples don't look anything like what I see in the JDK. For those specific cases, you should almost certainly be creating an enum that implements the desired interface. An interface describes a set of behaviors and really has no business maintaining a collection of its implementations.

-1

I wonder if there are reasons not to use it.

How about, um, compatibility with older JVMs?

Do you consider this a good idea in general?

No. It is a backwards-incompatible change that adds zilch to the expressivity of the language. Two thumbs down.

Are there some model situations where you strongly recommend classes?

I strongly recommend using classes to contain implementation details. An interface is really just meant to say "this Object supports operations XYZ" and that has nothing to do with any static methods you may think of putting in the interface declaration. This feature is like a recliner with a built-in mini-fridge. Sure it has some niche uses but it doesn't pull enough weight to deserve being mainstream.

UPDATE: Please no more downvotes. Clearly some people think static methods in interfaces are the bee's knees, and I'm hereby capitulating. I'd just as soon delete this answer but the comments attached to it are an interesting discussion.

2
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – maple_shaft
    Commented Dec 17, 2016 at 14:37
  • If I downvoted your question, I would do it because our first two answers are not real answers. New version of language brings new tools to make stuff easier, that is the very purpose of these new versions. The third answer is kinda lost in the rubble of busted first two.
    – Vlasec
    Commented Dec 20, 2016 at 15:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.