Default method in interface
As you know that an Interface in java can have only Abstract methods and a class, which implements interface must provide implementation of all abstract methods or the class must be declared abstract.
If there is an old interface, which has multiple implementation classes and I want to improve the interface by adding a new method (new functionality), it will break all existing implementations. Existing implementation classes must change and implement new method. That’s what happens before Java 8.
Java 8 introduced Interface Default Method, which is very helpful in situation like above. Default method in interface allows providing default implementation of new method in interface itself. Default implementation is applicable to existing implementation classes, which do not implement new method. Implementation class can implement new method and override default implementation.
public interface Calculator {
int add(int a, int b);
int subtract(int a, int b);
}
Here is implementation of Calculator interface
public class ClassicCalculator implements Calculator {
@Override
public int add(int a, int b) {
return (a + b);
}
@Override
public int subtract(int a, int b) {
return (a - b);
}
}
Lets use ClassicCalculator
public class MainApp {
public static void main(String[] args) {
Calculator classicCalculator = new ClassicCalculator();
System.out.println("ClassicCalculator: 2 + 3 = " + classicCalculator.add(2, 3));
System.out.println("ClassicCalculator: 10 - 4 = " + classicCalculator.add(10, 4));
}
}
/*
--- Output ---
ClassicCalculator: 2 + 3 = 5
ClassicCalculator: 10 - 4 = 14
*/
Lets add a new method multiply in Calculator interface. Mark new method as default method using default keyword and provide default implementation. Default implementation throws exception indicating operation is not supported. With the default method existing ClassicCalculator will work fine.
public interface Calculator {
int add(int a, int b);
int subtract(int a, int b);
default int multiply(int a, int b) {
throw new RuntimeException("Operation not supported. Upgrade to UltimateCalculator");
}
}
public class MainApp {
public static void main(String[] args) {
Calculator classicCalculator = new ClassicCalculator();
System.out.println("ClassicCalculator: 2 + 3 = " + classicCalculator.add(2, 3));
System.out.println("ClassicCalculator: 10 - 4 = " + classicCalculator.add(10, 4));
System.out.println("ClassicCalculator: 10 * 4 = " + classicCalculator.multiply(10, 4));
}
}
/*
--- Output ---
ClassicCalculator: 2 + 3 = 5
ClassicCalculator: 10 - 4 = 14
Exception in thread "main" java.lang.RuntimeException: Operation not supported. Upgrade to UltimateCalculator
at com.readtorakesh.java8.interface_default_method.Calculator.multiply(Calculator.java:8)
at com.readtorakesh.java8.interface_default_method.MainApp.main(MainApp.java:10)
*/
Lets write another implementation of Calculator interface which implements new multiply method as well.
public class UltimateCalculator implements Calculator {
@Override
public int add(int a, int b) {
return (a + b);
}
@Override
public int subtract(int a, int b) {
return (a - b);
}
@Override
public int multiply(int a, int b) {
return (a * b);
}
}
Lets use UltimateCalculator and not output of multiple method.
public class MainApp {
public static void main(String[] args) {
Calculator ultimateCalculator = new UltimateCalculator();
System.out.println("UltimateCalculator: 2 + 3 = " + ultimateCalculator.add(2, 3));
System.out.println("UltimateCalculator: 10 - 4 = " + ultimateCalculator.add(10, 4));
System.out.println("UltimateCalculator: 10 * 4 = " + ultimateCalculator.multiply(10, 4));
}
}
/*
--- Output ---
UltimateCalculator: 2 + 3 = 5
UltimateCalculator: 10 - 4 = 14
UltimateCalculator: 10 * 4 = 40
*/
Static method in interface
Starting Java 8 interface can also have static method. Like static method of a class, static method of an interface can be called using Interface name.
Lets add a static method display in Calculator interface.
public interface Calculator {
int add(int a, int b);
int subtract(int a, int b);
default int multiply(int a, int b) {
throw new RuntimeException("Operation not supported. Upgrade to UltimateCalculator");
}
static void display(String value) {
System.out.println(value);
}
}
Lets call display static method.
public class MainApp {
public static void main(String[] args) {
Calculator ultimateCalculator = new UltimateCalculator();
Calculator.display("UltimateCalculator: 2 + 3 = " + ultimateCalculator.add(2, 3));
Calculator.display("UltimateCalculator: 10 - 4 = " + ultimateCalculator.add(10, 4));
Calculator.display("UltimateCalculator: 10 * 4 = " + ultimateCalculator.multiply(10, 4));
}
}
/*
--- Output ---
UltimateCalculator: 2 + 3 = 5
UltimateCalculator: 10 - 4 = 14
UltimateCalculator: 10 * 4 = 40
*/
Default method and multiple inheritance
Java does not allow a class to extend multiple classes but a class can implement multiple interfaces. If a class implement two interfaces and both interfaces define default method of same signature, the implementation class must override default method and either provide new implementation or it call default method of either of the interfaces. To call default method of a particular interface it can use InterfaceName.super.method(…) syntax.
interface SampleInterface1{
default void showMethod() {
System.out.println("SampleInterface1.showMethod()");
}
}
interface SampleInterface2{
default void showMethod() {
System.out.println("SampleInterface2.showMethod()");
}
}
class SampleImplClass implements SampleInterface1, SampleInterface2 {
@Override
public void showMethod() {
//call default method of SampleInterface1
SampleInterface1.super.showMethod();
}
}
public class MainApp {
public static void main(String[] args) {
new SampleImplClass().showMethod();
}
}
/*
--- Output ---
SampleInterface1.showMethod()
*/
Abstract Class versus Interface with default method
- Abstract class is more constructive in nature. It can have constructor but Interface can’t.
- Abstract class can be stateful. It can have member variables but Interface can’t
- Main purpose of Interface Default Method is to enhance existing interface without breaking existing implementations. We should not practice using default method for new interfaces. For new development always use Abstract Class instead of Interface with default method
Please share it and help others if you found this blog helpful. Feedback, questions and comments are always welcome.
Further Reading
- Optional in Java 8 to avoid NullPointer
- Functional Interface – Java8
- Lambda Expression Basics and Syntax – Java8
Reference
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
1 Comment