Java 8 language features in Nutshell - Part 1


Hello Friends,

It has been quite long when Java 8 was released and now it is getting used more and more. In this post, we will discuss following topics of Java 8.

1.Functional Interface
2.Lambda expression
3.Default Methods



1. Functional Interface

What is Functional Interface?

Interface with one and only one abstract method is a Functional Interface, as it is representing exactly one functionality. However, a functional Interface can have n number of default as well as static methods.

The syntax for Functional Interface

 It is just like any other interface. The only difference is that it should have
@FunctionalInterface annotation at the top.
  @FunctionalInterface
  interface fly {

  }
 
Also, we need to understand that, even if we don't use @FunctionalInterface annotation, but an interface has only one abstract method, then by default that interface will be treated as Functional Interface, but it is always recommended to use @FunctionalInterface annotation for a functional interface.

The advantage with putting @FunctionalInterface annotation is that today you might define an interface as Functional Interface by having only one abstract method in it without using @FucntionalInterface annotation and keeping in mind that lambdas can be written for this Functional interface,but if you have big project with lots of developers working on that project, then there are great chances that later someone can add another method to your Functional Interface which then will  not actually remain Functional Interface as it will have more than one abstract method and at the same time, it will break all the already written lambda expressions as well.

So if your intention is to write an interface using which lambdas can be written, better mark it with @FunctionalInterface.

Main Purpose of Functional Interface

The main purpose of introducing Functional interface in Java 8 is to allow writing a lambda expression against the Functional Interface as lambda expression method signature is validated against the Functional Interface's method.

Example of Functional Interface

@FunctionalInterface
public interface Calculator {
    int add(int a,int b);

}

public class Test {
    public static void main(String[] args){
        Calculator calculator = (a,b) -> a + b;
        System.out.println("Sum is:"+calculator.add(4,6));
    }
}
There are many inbuilt Functional Interface which has been added in JDK 1.8 in the java.util.function package, which can be used to write a lambda expression.

Predicate
Consumer
Supplier
Function

2. Lambda expression

What is Lambda expression?

Lambda expression in simple words is the implementation of the Functional Interface method. Normally we write implementations in the methods, but in case of lambda's, there is no method in which it is written so we can think of lambda expression as an anonymous function i.e. a function with implementation but without any name.

The syntax of Lambda expression?

(Comma separated parameters )  + arrow symbol + single  expression or block of statements;

Main Purpose of Lambda Expression

The main reason to introduce Lambda expression in Java 8 was to enable Functional Programming in Java. Before Java 8, If we wanted to have some functionality which we wanted to execute inline, like on click of a button and this code did not make sense to be put in a separate class, we were doing that by creating an anonymous class. In these cases, we are usually trying to pass functionality as an argument to another method, such as what action should be taken when someone clicks a button. The problem with anonymous class is that even if we are having a very small implementation, code written using anonymous class is very verbose and unclear. With lambda expression, we can write code in more readable and concise manner.

Example of Lambda expression

Let us see how to write a lambda expression.
From above example, we have following interface
@FunctionalInterface
public interface Calculator {
    int add(int a,int b);

}

Lambda expression derives it's signature from the method of the Functional interface, so using add method's signature we will write our first lambda expression. Left side within the parenthesis we will have parameters, then arrow symbol and then a block of statement.
(int a,int b) ->{ 
    return a + b;
};
if you look at it closely, it is method definition without any method name. Say it would have a name, then it would have looked like as below after removing arrow symbol :
add(int a,int b) { 
   return a + b;
};
Now to convert it into Lambda, Java designers removed name i.e. add and put an arrow symbol after parameters, such that it became as below :
(int a, int b) ->{ 
   return a + b;
};
Now because compiler checks for the signature of the lambda expression by matching it with the signature of the Functional Interface method, so the compiler can guess the type of the parameters passed in the lambda expression by checking against the Functional Interface method. So we can remove types from parameters, such that our modified lambda expression will look like as below :
(a,b) -> { 
   return a + b;
};

Apart from guessing the type of the parameters, the compiler will also get to know that this lambda expression is going to return int value by looking at the return type of method declared in the Functional Interface, so we can remove return keyword as well.
(a,b) -> { 
   a + b;
};
Now because in above lambda expression we have only one statement in the block, we can get rid of the braces as well, so modified lambda will look like as below :

(a, b) -> a + b;

3. Default methods in interface

What is default method?

Default methods are the methods with some default implementation which can be defined in an interface.

Before Java8, we could not have methods with definitions in the interface, however with Java8, we can have methods with the definition as well in an interface, but these are special kind of method, in the sense that they have default keyword in their signature.

The main purpose of introducing Default Methods

The main reason for adding default method in Java is to make code backward compatible, even when new method(s) are introduced in the already existing interfaces because if default methods do not exist and we try to add a new method in an already existing interface, it will break all the implementation classes, as those existing implementation classes have to implement the newly introduced method(s) in the interface.

The syntax for Default Method

public interface InterfaceTest{
   default public void testDefault(){

   }
}

Example of Default Method

The iterable interface which is there since JDK 1.5 has got following new default method in it in JDK 1.8 release. Now as Collection interface extends this iterable interface and collections like List, Set extends Collection interface, this method is available to these collections by default to iterate over the elements of these collections.
public interface Iterable<T> {
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }

    }
}
If this method would not have been default, and it would have been added to Iterable interface, it would have forced all the classes which are implementing this interface (via Collection interface) to implement this method and hence, would have broken all those classes. So to make code like forEach method work without breaking the existing code, default methods are introduced in JDK 1.8.

Thanks for reading Java 8 language features -Part1. Continue to part-2 Java 8 Language Features in nutshell - Part 2

Please share it, if you think it was useful so that others can also benefit from it.