Friday, 30 September 2016

Java 8 | Functional Interface

What is the functional interface?
Functional interfaces are new features in Java 8 which permit exactly one abstract method inside them. These interfaces are also called Single Abstract Method(SAM) interfaces. From Java 8 onwards, lambda expressions can be used to represent the instance of a functional interface. A functional interface can have any number of default methods. Runnable, ActionListener, Comparable are some of the examples of functional interfaces.

Example of Functional Interface In Java 8?
We are creating the thread using the Runnable (a functional Interface) in Java 8.

package com.java8.lambda;
/**
 * @author rajesh.dixit
 * @since Aug 21, 2018 10:26:08 AM
 */
public class MyThread {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Runnable runnable = () -> {
            System.out.println("Thread has been started!");
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }
}

@FunctionalInterface Annotation
Java 8 introduces an annotation i.e. @FunctionalInterface, which can be used for compiler level errors when the interface we have annotated violates the contracts of Functional Interface.

@FunctionalInterface
interface MyFunctionalInterface {
     public void onlyMethod();
    
}

It will throw error while defining another method in the functional interface.

Unexpected @FunctionalInterface annotation
@FunctionalInterface ^ MyFunctionalInterface is not a functional interface
multiple non-overriding abstract methods found in interface MyFunctionalInterface


java.util.function package @FunctionalInterface
The java.util.function package in Java 8 contains many functional interfaces:

Predicate: The Predicate interface has an abstract method test which gives a Boolean value as a result of the specified argument.

public Predicate {
    public boolean test(T t);
}

BinaryOperator: The BinaryOperator interface has an abstract method apply which takes two arguments and returns a result of the same type.

public interface BinaryOperator {
     public T apply(T x, T y);
}

Function: The Function interface has an abstract method apply which takes an argument of type T and returns a result of type R.

public interface Function {
   public R apply(T t);
}

The important points about functional interfaces
1) Conceptually, a functional interface has exactly one abstract method. The second abstract method is not permitted in a functional interface.

A functional interface is valid even if the @FunctionalInterface annotation would be omitted. It is only for informing the compiler to enforce single abstract method inside interface.  If we remove @FunctionalInterface annotation then we are allowed to add another abstract method, but it will make the interface non-functional interface.

@FunctionalInterface
interface MyFunctionalInterface {
     public void onlyMethod();

     default void defaultMethod() {
           System.out.println("Default method ");
     }
}

Since default methods have an implementation, they are not abstract. Since default methods are not abstract you’re free to add default methods to your functional interface as many as you like.

2) If an interface declares an abstract method overriding one of the public methods of java.lang.Object that also does not count toward the interface’s abstract method count since any implementation of the interface will have an implementation from java.lang.Object or elsewhere.


Comparator is a functional interface even though it declared two abstract methods. Why?
If an interface declares an abstract method overriding one of the public methods of java.lang.Object, that also does not count toward the interface's abstract method count since any implementation of the interface will have an implemmation from java.lang.Object or elsewhere.
Since equals is a public method of Object, this statement applies; thus, for Comparator only the compare method contributes to the abstract method count.




Java 8 | Interface - default method and static method

Java 8 interface changes include static methods and default methods in interfaces. Prior to Java 8, we could have only method declarations in the interfaces. But from Java 8, we can have default methods and static methods in the interfaces.

Java interface default method
If we want to add additional methods in the older version of interfaces, it will require the change in all the implementing classes. As interface grows old, the number of classes implementing it might grow to an extent that it’s not possible to extend interfaces. That’s why when designing an application, most of the frameworks provide a base implementation class and then we extend it and override methods that are applicable for our application.

Default methods 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.

Implementation of the default Method
To create a default method in the Java interface, we need to use “default” keyword with the method signature. For example,
package java.algoforum.inter;
public interface Interface1 {
     void method1();
    
     default void log(String str){
           System.out.println("Interface 1 logging::"+str);
     }
}

log(String str) is the default method so it is not mandatory to provide for the default method in the class which implements Interface1. This feature will help us in extending interfaces with additional methods, all we need is to provide a default implementation.

The important use case for diamond problem
Let’s say we have another interface with the following methods:
package java.algoforum.inter;
public interface Interface2 {
     void method2();

     default void log(String str){
           System.out.println("Interface 2 logging::"+str);
     }
}

Java doesn’t allow us to extend multiple classes because it will result in the “Diamond Problem” where the compiler can’t decide which superclass method to use. With the default methods, the diamond problem would arise for interfaces too. Because of a class is implementing both Interface1 and Interface2 and doesn’t implement the common default method, the compiler can’t decide which one to choose.

Extending multiple interfaces are an integral part of Java, we can find it in the core java classes as well as in most of the enterprise application and frameworks. So to make sure, this problem won’t occur in interfaces, it’s made mandatory to provide the implementation for common default methods of interfaces. So if a class is implementing both the above interfaces, it will have to provide the implementation for log() method otherwise the compiler will throw compile time error.

A simple class that is implementing both Interface1 and Interface2 will be:
package com.algoforum.inter;
interface Interface1 {
     public void method1();

     default void log(String str) {
           System.out.println("Interface1 logging::" + str);
     }
}

interface Interface2 {
     public void method2();

     default void log(String str) {
           System.out.println("Interface2 logging::" + str);
     }
}

public class TestClass implements Interface1, Interface2 {

     @Override
     public void method2() {
     }

     @Override
     public void method1() {
     }

     @Override
     public void log(String str) {
           System.out.println("Test Class logging::" + str);
     }
}

Extending Interfaces That Contain Default Methods
When you extend an interface that contains a default method, you can do the following:
  • Not mention the default method at all, which lets your extended interface inherit the default method.
  • Re-declare the default method, which makes it abstract.
  • Redefine the default method, which overrides it.
Important points about java interface default methods:
This feature is also known as Defender Methods or Virtual extension methods. One of the major reasons for introducing default methods in interfaces is to enhance the Collections API in Java 8 to support lambda expressions.

1. Java interface default methods will help us in extending interfaces without having the fear of breaking implementation classes.
2. Java interface default methods have the bridge down the differences between interfaces and abstract classes.
3. Java 8 interface default methods will help us in avoiding utility classes, such as all the Collections class method can be provided in the interface itself.
4. Java interface default methods will help us in removing base implementation classes, we can provide the default implementation and the implementation classes can choose which one to override.

Related Posts Plugin for WordPress, Blogger...