Default Interface Methods

by:

CommonJavaSERelevant topics

With the release of Java 8, the authors of Java have introduced a new type of method to an interface, referred to as default method. A default method is a method defined within an interface with the default keyword in which a method body is provided, unlike “regular” method, which is assumed to be abstract and may not have a method body. Classes have the option to override the default method if they need to, but are not required to do so.

The following is an example of a default method defined in an interface :

public interface IsWarmBlooded {
boolean hasScales();
public default double getTemperature() {
return 10.0;
}
}

The example defines two interface methods, one is a normal abstract and another is default. The first method is terminated with a semicolon and doesn’t provide a body, whereas the second provides a body. Besides, both methods are public. It’s important to note that declaring default interface methods as public is excessive since all interface methods are public.

The following are the default interface method rules developers must be familiar with :

  • A default method may only be declared within an interface and not within a class or abstract class
  • A default method must be marked with the default keyword and it must provide a method body
  • A default method is not assumed to be static, final or abstract as it may be used or overridden by a class implementing an interface
  • Like all methods in an interface, a default method is assumed to be public and will not compile if marked as private or protected

According to the rules listed above, the following code snippets will not compile :

public interface Carnivore {
public default void eatMeat(); // DOES NOT COMPILE
public int getRequiredFoodAmount() { // DOES NOT COMPILE
return 13;
}
}

Unlike interface variables, which are assumed static class members, default methods cannot be marked as static and require an instance of the class implementing the interface to be invoked. They also can’t be marked as final or abstract as they are allowed to be overridden in subclasses but are not required to be overridden.

When an interface extends another interface that contains a default method, it may choose to ignore the default method, then the default implementation for the method will be used. Alternatively, the interface may override the definition of the default method using the standard rules for method overriding, such as not limiting the accessibility of the method and using covariant returns. Finally, the interface may redeclare the method as abstract, requiring classes that implement the new interface to explicitly provide a method body. Analogous options apply for an abstract class that implements an interface.

In the following example SharkFamily interface extends HasFins, overrides one default interface method and redeclares a second interface method as abstract :

public interface HasFins {
public default int getNumberOfFins() {
return 4;
}
public default double getLongestFinLength() {
return 20.0;
}
public default boolean doFinsHaveScales() {
return true;
}
}

public interface SharkFamily extends HasFins {
public default int getNumberOfFins() {
return 8;
}
public double getLongestFinLength();
public boolean doFinsHaveScales() { // DOES NOT COMPILE
return false;
}
}

Method doFinsHaveScales() of interface SharkFamily is defined incorrectly as it has a body but is not marked as default.

Default Methods and Multiple Inheritance

By allowing default methods in interfaces, coupled with the fact a class may implement multiple interfaces, Java has opened the door to multiple inheritance problems. For example, what will the following code output ?

public interface Walk {
public default int getSpeed() {
return 5;
}
}

public interface Run {
public default int getSpeed() {
return 10;
}
}

public class Cat implements Walk, Run { // DOES NOT COMPILE
public static void main(String[] args) {
System.out.println(new Cat().getSpeed());
}
}

Cat inherits the two default methods for getSpeed(), so this is an ambiguous situation, it is not clear whether the code should output 5 or 10. If a class implements two interfaces that have default methods with the same signature, the compiler will throw an error. There is an exception to this rule, though : if the subclass overrides the duplicate default methods, the code will compile without issue – the ambiguity about which version of the method to call has been removed. See the following example :

public class Cat implements Walk, Run {
public int getSpeed() {
return 1;
}

public static void main(String[] args) {
System.out.println(new Cat().getSpeed());
}
}

The code will compile and output 1.

Leave a Reply

Your email address will not be published. Required fields are marked *