Why Use, Usage and Accessing overridden of default methods


Default Methods

Default Method introduced in Java 8, allows developers to add new methods to an interface without breaking the existing implementations of this interface. It provides flexibility to allow the interface to define an implementation which will be used as default when a class which implements that interface fails to provide an implementation of that method.


Basic usage of default methods

/**
* Interface with default method
*/
public interface Printable {
	default void printString() {
		System.out.println( "default implementation" );
	}
}
 
/**
* Class which falls back to default implementation of {@link #printString()}
*/
public class WithDefault
	implements Printable
{
}
 
/**
* Custom implementation of {@link #printString()}
*/
public class OverrideDefault
	implements Printable {
	@Override
	public void printString() {
		System.out.println( "overridden implementation" );
	}
}

The following statements

new WithDefault().printString();
new OverrideDefault().printString();

Will produce this output:

default implementation
overridden implementation

Accessing overridden default methods from implementing class

In classes, super.fun() will look in superclasses only. If you want to call a default implementation from a superinterface, you need to qualify super with the interface name: Fooable.super.fun().

public interface sample {
	default int fun() {return 3;}
}
 
	public class A extends Object implements sample {
	@Override
	public int fun() {
		//return super.fun() + 1; //error: no method fun() in java.lang.Object
		return sample.super.fun() + 1; //okay, returns 4
	}
}

Why use Default Methods?

The simple answer is that it allows you to evolve an existing interface without breaking existing implementations.

For example, you have Swim interface that you published 20 years ago.

public interface Swim {
    void backStroke();
}

We did a great job, our interface is very popular, there are many implementation on that around the world and you don't have control over their source code

public class FooSwimmer implements Swim {
    public void backStroke() {
        System.out.println("Do backstroke");
    }
}

After 20 years, you've decided to add new functionality to the interface, but it looks like our interface is frozen because it will break existing implementations.

Luckily Java 8 introduces brand new feature called Default method.

We can now add new method to the Swim interface.

public interface Swim {
    void backStroke();
    default void sideStroke() {
        System.out.println("Default sidestroke implementation. Can be overridden");
    }
}

Now all existing implementations of our interface can still work. But most importantly they can implement the newly added method in their own time.

One of the biggest reasons for this change, and one of its biggest uses, is in the Java Collections framework. Oracle could not add a foreach method to the existing Iterable interface without breaking all existing code which implemented Iterable. By adding default methods, existing Iterable implementation will inherit the default implementation.

Basic Programs