Tuesday, October 03, 2017

Java 8 Interfaces: default and static methods

Java 8 introduces default static methods that enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces. While both static and default methods allow to add method implementations to interfaces, the difference is that you cannot override static methods. Both default and static methods are "public", and there is no need to explicitly declare them as public.

Default Interface Methods

Default methods in interfaces allow you to add default implementation to methods that you can use as is, or override. But adding method implementation to interface introduces the problem of the classic multiple inheritance problem in C++ that was one of the main reasons for introducing interfaces in Java. Java avoids that problem by making it a compile time error if you introduce the classic "Diamond" inheritance while implementing multiple interfaces. If you extend create a diamond inheritance structure, Java 8 forces you to implement the method that is inherited multiple times through different interface. We will take a look at that behavior in the following example.
Create default methods
Default methods can be created by simply defining the method with the default keyword.
package interfaces;

public interface InterfaceA {

 String add(int a, int b);

 String subtract(int a, int b);

 default String hello(String str) {
  return "InterfaceA : " + str;
 }
}
We will use the following two interfaces to demonstrate the behavior of in case of multiple inheritance. Both InterfaceB and InterfaceC extend InterfaceA, but will implement different methods as default methods. Finally, we will create an implementation class that implements both InterfaceB and InterfaceC.
InterfaceB
package interfaces;

public interface InterfaceB extends InterfaceA {
 @Override
 default String add(int a, int b) {
  return "InterfaceB Add : " + (a + b);
 }

 String subtract(int a, int b);

}
InterfaceC
package interfaces;

public interface InterfaceC extends InterfaceA {

 String add(int a, int b);

 @Override
 default String subtract(int a, int b) {
  return "InterfaceC : " + (a + b);
 }
}
Implementation class and the super keyword
The implementation class DefaultMethodsExample implements InterfaceB and InterfaceC. However, since there is a conflict, Java 8 forces you to implement the add() and subtract(). And since there is no conflict with the hello() methods, we don't have to implement it. You will also notice what you can use the InterfaceC.super call in the the subtract method can be used to invoke the specific Interface you want the implementation to come from.
package interfaces;

public class DefaultMethodsExample implements InterfaceB, InterfaceC {

 @Override
 public String subtract(int a, int b) {
  return InterfaceC.super.subtract(a, b);
 }


 @Override
 public String add(int a, int b) {
  return "DefaultMethodsExample : " + (a + b);
 }

 public static void main(String[] args) {
  DefaultMethodsExample example = new DefaultMethodsExample();
  System.out.println(example.hello("world"));
  System.out.println(example.add(1, 2));
  System.out.println(example.subtract(6, 5));
 }

}

Static Interface Methods

Static methods are also public like default methods, but you cannot override the static methods. The following example shows one use of the static method. We will create a static method in InterfaceA from the above example as shown below
package interfaces;

public interface InterfaceA {

 String add(int a, int b);

 String subtract(int a, int b);

 default String hello(String str) {
  return "InterfaceA : hello " + str;
 }
 
 static String staticHello(String str) {
  return "InterfaceA Static : hello " + str;
 }
}
To invoke the static method staticHello(), we can invoke it like any static method of a class InterfaceA.staticHello as shown below.
package interfaces;

public class DefaultMethodsExample implements InterfaceB, InterfaceC {

 @Override
 public String subtract(int a, int b) {
  return InterfaceC.super.subtract(a, b);
 }


 @Override
 public String add(int a, int b) {
  return "DefaultMethodsExample : " + (a + b);
 }

 public static void main(String[] args) {
  DefaultMethodsExample example = new DefaultMethodsExample();
  System.out.println(example.hello("world"));
  System.out.println(example.add(1, 2));
  System.out.println(example.subtract(6, 5));
  System.out.println(InterfaceA.staticHello("World"));
 }

}

7 comments:

Popular Posts