Last Updated:

Interfaces in Java 8. Static methods, default methods, functional interfaces

Interfaces in Java 8 have undergone the biggest changes. For example, in Java 7, we could only declare methods in interfaces. But starting with Java 8, we can use default methods and static methods in interfaces. Read more about the innovations in the interfaces under the cut

Designing interfaces is hard work. If we want to add additional methods to interfaces, this will require changes in all classes that implement this interface.

From practice: the longer we maintain the code, the more the interface overgrows with classes and there comes a time when it will be too expensive to maintain it. That's why, when designing software, most programmers create a class with a basic implementation, and then inherit it and override the desired methods.

Default methods in Java 8 interfaces

To create a default method in the interface, we have to use the keyword . Let's use a simple example to create a default method.default

Note that in the interface above, the method is the default method. Now that any class will implement interface Interface1, it is not necessary to provide an implementation of the default methods (in our case, it is the method ). Functionality with default methods will help us a lot in the future, when many classes will already implement this interface.

log(String str)log(String str)

And now let's look at another interface:

We know that Java doesn't allow us to inherit from multiple classes because it will lead to a diamond-shaped problem where the compiler can't decide which superclass method to use. Now, with the advent of default methods, this problem will arise for interfaces as well!

The thing is that if a class implements both , and does not implement a common method by default, then the compiler cannot decide what to choose.Interface1Interface2

Inheritance of multiple interfaces is an integral part of Java, so now in Java 8 we need to make sure that this problem does not occur in the interfaces. So, if a class implements both of the above interfaces, then it will have to provide an implementation of the method , otherwise the compiler will throw errors.log(String str)

For now, let's look at an example of a class that implements both interfaces and provides a default method implementation:

Briefly about the main thing. Default methods in interfaces

  1. The default methods help you implement interfaces without fear of disrupting other classes.
  2. The default methods in Java 8 avoid creating utility classes because all the necessary methods can be represented in the interfaces themselves.
  3. The default methods give classes the freedom to choose the method to override.
  4. One of the main reasons for implementing the default methods is the ability of collections (in Java 8, of course) to use lambda expressions.
  5. If any class in the hierarchy has a method with the same signature, the default methods become irrelevant. The default method cannot override a method of the . The argument is very simple: this is because the object is the base class for all Java classes. So, even if we have methods of the class defined as the default methods in the interfaces, it will be useless because the object class method will always be used. That's why, to avoid confusion, we can't write standard methods that override the methods of the .java.lang.ObjectObjectObject

Static methods in interfaces

Static methods are similar to the default methods, except that we can't override them in classes that implement the interface. This functionality helps us to avoid undesirable results that may appear in child classes.

Let's look at the use of static methods with a simple example:

As you can see in the example above, we used the ternary operator to reduce the amount of code.

Now let's look at the class that implements the interface above:

Note that it is a simple method of the class, and it does not override the method of the interface. And what happens if we add an annotation @Override to the method? This will result in an error.isNull(String str)isNull()

The output of the above program is as follows:

Now let's change the static keyword in the interface to . The result of the execution is presented below:default

Static methods are visible only for interface methods. If we remove the method from the class , we will no longer be able to use it for the . However, like other static methods, we can use the class name to access them.isNull()MyDataImplMyDataImpl

For example, you can write it this way:

// so you can write
boolean result = MyData.isNull("abc");

Briefly about the main thing. Static methods in interfaces

  1. The static methods in the interface are part of the interface, we cannot use it for the objects of the implementation class.
  2. Static methods in an interface are good for providing helper methods, such as null checking, sorting collections, and so on.
  3. Static methods in an interface help provide security by preventing classes that implement the interface from overriding them.
  4. We cannot define static methods for class methods because we will get a compilation error: "This static method cannot hide the instance method from Object". That's because you can't 🙂 do that in Java. That is, it is the base class for all classes and we cannot use a static method and yet such a method with the same signature.ObjectObject
  5. We can use static interface methods to avoid creating helper classes, that is, to move all static methods to the appropriate interface. This method is easy to use and quick to find.

Functional interfaces

At the end of the article, I would like to give a brief introduction to functional interfaces.

An interface with a single abstract method is a functional interface.

In Java 8, a new annotation was introduced to denote an interface that is functional. The new annotation is added to avoid accidentally adding abstract methods to the functional interface. It is not mandatory, but it is a good practice of writing code.@FunctionalInterface@FunctionalInterface

Functional interfaces are a long-awaited feature of Java 8 because it allows us to use lambda expressions to instantiate such interfaces. A new package with many functional interfaces has been added.java.util.function

We'll look at functional interfaces and lambda expressions in future posts. Stay tuned to the Java 8 Features and Innovations section.