Before Java 8, interfaces could have only abstract methods. The implementation of these methods has to be provided in a separate class. So, if a new method is to be added in an interface, then its implementation code has to be provided in the class implementing the same interface. To overcome this issue, Java 8 has introduced the concept of default methods which allow the interfaces to have methods with implementation without affecting the classes that implement the interface.
// A simple program to Test Interface default // methods in java interfaceTestInterface{ // abstract method publicvoidsquare(int a); // default method defaultvoidshow() { System.out.println("Default Method Executed"); } } classTestClassimplementsTestInterface{ // implementation of square abstract method publicvoidsquare(int a) { System.out.println(a*a); } publicstaticvoidmain(String args[]) { TestClass d =newTestClass(); d.square(4); // default method executed d.show(); } }
Output:
16
Default Method Executed
The default methods were introduced to provide backward compatibility so that existing intefaces can use the lambda expressions without implementing the methods in the implementation class. Default methods are also known as defender methods or virtual extension methods.
Static Methods:
The interfaces can have static methods as well which is similar to static method of classes.
// A simple Java program to TestClassnstrate static // methods in java interfaceTestInterface{ // abstract method publicvoidsquare (int a); // static method staticvoidshow() { System.out.println("Static Method Executed"); } } classTestClassimplementsTestInterface{ // Implementation of square abstract method publicvoidsquare (int a) { System.out.println(a*a); } publicstaticvoidmain(String args[]) { TestClass d =newTestClass(); d.square(4); // Static method executed TestInterface.show(); } }
Output:
16
Static Method Executed
Default Methods and Multiple Inheritance
In case both the implemented interfaces contain deafult methods with same method signature, the implementing class should explicitly specify which default method is to be used or it should override the default method.
// A simple Java program to demonstrate multiple // inheritance through default methods. interfaceTestInterface1{ // default method defaultvoidshow() { System.out.println("Default TestInterface1"); } } interfaceTestInterface2{ // Default method defaultvoidshow() { System.out.println("Default TestInterface2"); } } // Implementation class code classTestClassimplementsTestInterface1,TestInterface2{ // Overriding default show method publicvoidshow() { // use super keyword to call the show // method of TestInterface1 interface TestInterface1.super.show(); // use super keyword to call the show // method of TestInterface2 interface TestInterface2.super.show(); } publicstaticvoidmain(String args[]) { TestClass d =newTestClass(); d.show(); } }
Output:
Default TestInterface1
Default TestInterface2
Important Points:
Interfaces can have default methods with implementation from java 8 onwards.
Interfaces can have static methods as well similar to static method of classes.
Default methods were introduced to provide backward compatibility for old interfaces so that they can have new methods without effecting existing code.
Problem :
Fortunately, rules are available to resolve methods when a derived type inherits method definitions with the same name from different base types. Let us discuss two important scenarios here.
Scenario 1: If two super interfaces define methods with the same signature, the compiler will issue an error. We have to resolve the conflict manually.
Error:(9, 8) java: class Diamond inherits unrelated defaults for foo() from types Interface1 and Interface2
In this case, resolve the conflict manually by using the super keyword within the Diamond class to explicitly mention which method definition to use:
public void foo() { Interface1.super.foo(); }
After this method definition is added in the Diamond class and executed, this program prints: Interface1's foo
Scenario 2: If a base class and a base interface define methods with the same signature, the method definition in the class is used and the interface definition is ignored.
class BaseClass {
public void foo() { System.out.println("BaseClass's foo"); }
}
interface BaseInterface {
default public void foo() { System.out.println("BaseInterface's foo"); }
}
public class Diamond extends BaseClass implements BaseInterface {
public static void main(String []args) {
new Diamond().foo();
}
}
No compiler error in this case: the compiler resolves to the definition in the class and the interface definition is ignored. This program prints “Base foo”. This can be considered as “class wins” rule. This rule helps maintain compatibility with versions prior to Java 8. How? When a new default method is added in an interface, it may happen to have the same signature as a method defined in a base class. By resolving the conflict by “class wins” rule, the method from the base class will always be selected.