7.2.  Define and use a default method of an interface and describe the inheritance rules for the default method

[Note]

Interface Default Methods

Java 8 introduces default method new feature, which allows developer to add new methods to the interfaces without breaking the existing implementation of these interfaces. It provides flexibility to allow interface define implementation which will use as default in the situation where a concrete class fails to provide an implementation for that method.

By adding the keyword default before the method's access modifier in GreeterIntf interface and adding implementation inside interafce, we do not have to provide implementation for the method greet() in class Greeter:

interface GreeterIntf {
    default public void greet() {
        System.out.println("Hi");
    }
}

class Greeter implements GreeterIntf {
    // a valid class in Java 8
}

public class DefClass {
    public static void main(String[] args) {
        Greeter g = new Greeter();
        g.greet();
    }
}
					 

JVM method look up order

With default interface methods, the JVM now needs to search interfaces for method implementations. Naturally, methods present in the object's class or super classes are prioritized over the default implementation in an interface. Thus, method lookup in Java 8 now works as follows:

  1. Check the class of the object for a method with the given name and signature. If present, use that method.

  2. Else, recursively from bottom to up check the class' super types for a method with the given name and signature.

  3. Check the object's iterfaces and their superinterfaces for a default method with the given name and signature.

  4. If no suitable method is found, throw a NoSuchMethodError.

Default Method and Multiple Inheritance Ambiguity Problems

Since Java class can implement multiple interfaces and each interface can define a default method with same method signature, therefore, the inherited methods can conflict with each other.

Consider the following example, which fails to compile:

interface GreeterIntf1 {
    default public void greet() {
        System.out.println("Hi");
    }
}

interface GreeterIntf2 {
    default public void greet() {
        System.out.println("Hello");
    }
}

class Greeter implements GreeterIntf1, GreeterIntf2 {
    // Compilation fails with error:
    // "class Greeter inherits unrelated defaults for greet() from types GreeterIntf1 and GreeterIntf2"
}
					

In order to work around situations like this, we will have to provide implementation for greet() method in the class Greeter, therefore overriding both methods in GreeterIntf1 and GreeterIntf2:

class Greeter implements GreeterIntf1, GreeterIntf2 {
    @Override
    public void greet() {
        System.out.println("Wazzup");
    }
}
					

If we want to specifically invoke one of the greet() methods in either GreeterIntf1 or GreeterIntf2, we can also do as follows:

class Greeter implements GreeterIntf1, GreeterIntf2 {
    @Override
    public void greet() {
        GreeterIntf2.super.greet();
    }
}
					

Difference between Default Method and Regular Method

Default method is different from the regular method in the sense that default method comes with default modifier. Additionally, methods in classes can use and modify method arguments as well as the fields of their class, but default method on the other hand, can only access its arguments as interfaces do not have any state.

In summary, default methods enable to add new functionality to existing interfaces without breaking older implementation of these interfaces.

Extending Interfaces That Contain Default Methods

When you extend an interface that contains a default method, you CAN do the following:

[Warning]

You cannot use default methods to override any of the non-final methods in the java.lang.Object class. For example, the following code fails to compile:

public interface Foo {
    default boolean equals(Object o) {
        return false;
    }
}
						

The reasoning is very simple, it is because Object is the base class for all the Java classes. So even if we have Object's method defined as default method in some interface, it will be useless because Object's method will always be used. That is why to avoid confusion, we cannot have default methods that are overriding Object class methods.

Professional hosting         Free 'Oracle Certified Expert Web Services Developer 6' Guide     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz