Default Methods or Extension Methods for Interfaces

Java 8 allows us to add non-abstract method implementation to interfaces by utilizing the default keyword.

Here is our first example:

interface Calculator {
    double calculateSqrt(int a);
 
    default double sqrt(int a) {
        return Math.sqrt(a);
    }
}

Besides abstract calculateSqrt method, there is one non-abstract default method with implementation. Concrete class which implements this interface just needs to implement calculateSqrt method.

Here’s the example showing anonymous object implementation.

final Calculator calculator = new Calculator() {
         @Override
	 public double calculateSqrt(int a) {
		return sqrt(a * 100);
         }
};

calculator.sqrt(16);           // 4.0 
calculator.calculateSqrt(16);  // 40.0

Quite allot of code for method implementation. We will see later how lambda expression helps us to implement one method object.

Functional Interfaces

All java developer should have used interfaces at least one of the following: java.lang.Runnable, java.util.Comparator, java.util.concurrent.Callable etc. These interfaces has some common features which is they have exactly one method defined.  These interfaces are also called Single Abstract Method interfaces (SAM Interfaces). These interfaces can be used as annonymous inner classes.

public class TemperatorConverter {
  public static void main(String[] args) {
    new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("New thread is created in Temperature Converter...");
      }
    }).start();
  }
}

In Java 8 these interfaces are recreated and standardized as Functional Interfaces. There is new annotation @FuncationInterface introduced, used for compile level errors and validate as Functional Interface. Functional interface should have exactly one method, compiler is aware of this annotation and warns you if you want to add another method.

@FuncationalInterface
public interface TemperatureConverter<F, C> {
       C convertFahrenheitToCelsius(F From);
}

The code is also valid if you remove @FuncationalInterface annotation, but no compile time validation.

TemperatureConverter<Double, Double> tempConverter = (from) -> ((from - 32)*5)/9;
Double celciousTemp = tempConverter.convertFahrenheitToCelsius(100.0);
System.out.println(celciousTemp); // 37.77