Before Java 8 interfaces could only contain static fields (usually simple constants) and abstract methods. Java 8 provided the ability to define concrete (default and static) methods in interfaces. This new language feature is used extensively in Java core packages.
Static methods
Static method in interface looks the same like in a normal class:
public interface Checker { ... public static boolean isNull(Object obj) { return obj == null; } ...
The main reason to add static methods to interfaces is to keep related utility methods in one place so that they can be easily used by subclasses, default methods in subinterfaces or by users of this interface.
Default methods
Default method looks like a typical class method but is defined inside an interface and contains default specifier. Let’s look at Collection.removeIf() default method:
default boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); boolean removed = false; final Iterator<E> each = iterator(); while (each.hasNext()) { if (filter.test(each.next())) { each.remove(); removed = true; } } return removed; }
Default method can access everything that is defined within this interface or is inherited by this interface, including:
- reference to this
- all abstract methods defined in this or super-interfaces
- all default or static methods defined in this or super-interfaces
- all static fields defined in this or super-interfaces
Default methods allow adding new functionality to existing interfaces without breaking all existing implementations – they preserve backwards compatibility. A class, that implements an interface with a default method, gets the default implementation from the interface but it can still override the default implementation.
Default and static methods in functional interfaces
The functional interface can contain multiple default and static methods and still be functional. In fact, default and static methods are not abstract and are not counted within the limit of exactly one abstract method. Here is an example:
@FunctionalInterface public interface Comparator<T> { int compare(T o1, T o2); .... default Comparator<T> reversed() { return Collections.reverseOrder(this); } public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) { return new Comparators.NullComparator<>(true, comparator); } ....
Extending interfaces which contain default methods
If we create a new interface which extends an interface which contains a default method, we have 3 possibilities:
- Not mention the default method in the new interface. This way the new interface will inherit the default method from parent.
- Override the default method by redefining it in the new interface and providing new method body. All subclasses and subinterfaces will use new definition of the default method.
- Declare the default method as abstract in the new interface. This way the default method must be overridden in subclasses or subinterfaces of the new interface.
Default method ambiguity
Sometimes we may want to implement two interfaces which contain default methods with the same method signature (name, parameters, and so on):
public interface InterfaceOne { default void doSomething() { ... } } public interface InterfaceTwo { default void doSomething() { ... } } public class MyClass implements InterfaceOne, InterfaceTwo { }
In this rare case the compilation will fail because Java compiler does not know which implementation of the default method it should choose for the class. To resolve this issue we have to explicitly redefine/redeclare the default method in the class. We have two possibilities here.
The first one is to simply override the default method in the class and provide new method body:
public class MyClass implements InterfaceOne, InterfaceTwo { public void doSomething() { // some code InterfaceOne.super.doSomething(); } }
Please, note that we are not using default keyword anymore. We can also use following syntax:
InterfaceOne.super.doSomething();
to call default implementation from one of the implemented interfaces.
Alternatively, we can declare the default method in the class as abstract:
public abstract class MyClass implements InterfaceOne, InterfaceTwo { public abstract void doSomething(); }
As a result the class must be made abstract also. This way we can somehow “postpone” the problem because the concrete subclass will have to redefine this default method.
Conclusion
Many static and default methods have been added to existing interfaces since Java 8 to simplify their usage and promote code reuse. Some of these interfaces include: Iterator, Iterable, Comparator, Collection.
Interface static methods can be used for providing utility methods. With Interface static methods we can secure an implementation by having it in static method as implementing classes can’t override them.
This post gives details about the interface static methods- https://netjs.blogspot.com/2015/05/interface-static-method-in-java-8.html