Share

engineering

4min read

Exploring Java 9. Private Interface Methods

Exploring Java 9. Private Interface Methods

This post is a part of a series. If you are interested in JShell, check out Part 1 and in order to explore Java Platform Module System, read Part 2.

Do you remember how the Java world looked like before there were Streams? Have you recently used the Iterable.forEach() method? Or maybe you like your lists sorted and frequently enjoy the benefits of having List.sort() method? With backwards compatibility in mind all the things I mentioned above (and many more) wouldn’t be so easily achievable for Java creators if it wasn’t for the default methods introduced in the 8th release. Now it’s clear that they have adapted really well. Java 9 is going to introduce its “younger brother in arms”—the private (static) interface methods.

Default interface methods

Let’s take a closer look at the default interface methods. But first—a quick reminder. The default interface methods have their bodies defined in the interface. They provide a default implementation that will be used on instances of the class implementing the interface. In case you need other implementation than the default one—the methods can be overridden. Take a look at the following code from Java8’s List interface. It’s the sort() method I mentioned:

public interface List<E> extends Collection<E> {

/* … */

  default void sort(Comparator<? super E> c) {
    Object[] a = this.toArray();
    Arrays.sort(a, (Comparator) c);
    ListIterator<E> i = this.listIterator();
    for (Object e : a) {
      i.next();
      i.set((E) e);
    }
  }

/* … */

}

As you probably suspect by now, thanks to the default implementation of the List.sort() method we now have sort() method in every class implementing the List interface. You can always check it by yourself (one quick way to do that is by using JShell I described before).

Why is it so important? The creators of Java 8 had faced a tough dilemma before introducing the default methods. They wanted to extend the existing collection interfaces (such as the one above) by adding methods like stream() or sort(). Adding such methods the old way (as abstract ones) wouldn’t do the job and would break the existing implementations of those interfaces (due to the methods that were not implemented). Putting them in some other classes (eg. sorting in Collections.java) is not so clean either. At the end of the day it would be nice if the lists could sort themselves, wouldn’t it?

Adding the default method concept solves both problems quite neatly. They extend existing implementations instead of breaking them. This simple yet powerful concept isn’t flawless though.

What about code duplication?

Suppose we have our own interface and provide two default methods in it, each one sharing some common code:

public interface Magician {

  void raiseWand();

  void raiseHands();

  void saySpell(String spell);

  default void throwAlohomoraSpell() {;
    raiseHands();
    raiseWand();

    saySpell("Alohomora!");
  }

  default void throwWingardiumLeviosaSpell() {
    raiseHands();
    raiseWand();

    saySpell("Wingardium leviosa!");
  }
}

Every time we add another “spell method” we need to copy and paste the initial actions. Our example is trivial for the purpose of this article but one can think of some initialization or validation code which needs to be copied in every default method. This is an unnecessary burden to have this kind of duplication (possible bugs in code, copying and pasting multiple times etc.).

In Java 8 we can avoid the copying by implementing an inner class of an interface:

public interface Magician {

  void saySpell(String spell);

  default void throwAlohomora() {
    MagicianHelper.prepareForMagic();
    saySpell("Alohomora!");
  }

  default void throwWingardiumLeviosa() {
    MagicianHelper.prepareForMagic();
    saySpell("Wingardium leviosa!");
  }

  class MagicianHelper {
    private static void prepareForMagic() {
      // do some preparation, Harry!
    }
  }
}

I personally don’t like this solution as:

  • it is somewhat hacky
  • it doesn’t hide details we don’t want to show to our API users: one still can access the MagicianHelper because it can’t be private
  • it makes it impossible to access methods form Magician interface in MagicianHelper class (so, in our example we cannot use raiseHands() and raiseWand() methods)

Private interface methods

In Java 9 we can easily solve the above-mentioned problems using private interface methods. We can define them in interfaces, as shown below:

public interface Magician {

  void raiseWand();

  void raiseHands();

  void saySpell(String spell);

  default void throwAlohomora() {
    prepareForMagic();

    saySpell("Alohomora!");
  }

  default void throwWingardiumLeviosa() {
    prepareForMagic();

    saySpell("Wingardium leviosa!");
  }

  private void prepareForMagic() {
    raiseHands();
    raiseWand();
  }
}

Thanks to private methods you don’t have to create artificial concepts like the MagicianHelper class. They are completely hidden—you have access to them only from the interface implementing it. Of course, the subinterfaces also do not see it. You can use all the methods declared in the interface while implementing the private method body: the default or the abstract ones (notice the raiseHands() and raiseWand() methods). All this, if used well, can help you make your API more concise and easier to use. Finally, private methods in interfaces can also be static. This can be useful especially in case of the public static interface methods also introduced in Java 8.

Conclusion:

Private interface methods naturally complement the default and static methods in interfaces that were introduced in Java8. This language feature is a part of JEP 213 called “Milling Project Coin”. It’s a set of “small language improvements” to be introduced in Java 9—just as it happened during the Java 7’s release (Project Coin). If you’re keen to learn the specifics and see what other Java language concepts are going to be polished, those two websites might be a good place to start. As Java 9 is finally knocking on the door the timing seems to be more than perfect!

Share

Łukasz

Senior Software Engineer

Did you enjoy the read?

If you have any questions, don’t hesitate to ask!

Did you enjoy the read?

If you have any questions, don’t hesitate to ask!