Introduction to Functional Interfaces and Lambda in Java 8

Pritam Panhale
4 min readOct 16, 2020

Before seeing what is a functional interface, we will see its history and how programming was done before functional interfaces and lambda expressions were not exist.

Anonymous Classes —

The concept of anonymous classes is least used and discouraged at a particular time and with the latest features like functional interfaces, it is totally obsolete. Let's see an example first and then we go into the details of it.

interface Shape {
String getShape();
}

public class FunctionalInterfaceDemo {

public static void main(String[] args) {
Shape circle = new Shape() {
@Override
public String getShape() {
return "I am a Circle";
}
};

System.out.println(processShapeObject(circle));
}

public static String processShapeObject(Shape shape) {
return shape.getShape();
}
}

In the above example, I have created a Shape interface which has an unimplemented method called getShape(). Like we know there can be multiple implementations of the Shape interface, for example, Circle, Square, triangle, etc (I am sticking here with classic java examples). You can see how the anonymous class has been created. There is another method in the program processShapeObject() which is expecting an Object of type Shape which will simply call getShape() method of Shape and return its value. So when we create a new instance of Shape, we are creating a new class, overriding the method getShape(). Only the thing is that the class does not have any name which is implementing Shape interface. It is created instantly hence it is called anonymous.

If you see the example above, writing an anonymous class is a little bit clumsy, unorganized and we need to repeat the whole syntax of writing a new class altogether. So here comes the functional interfaces with a lambda expression to overcome and simplify the programming paradigm.

Functional Interface — It's a regular interface with only one method.

Java provides an annotation called @FunctionalInterface which an interface can have at an interface/class level, but it is not mandatory to have this annotation. Though it is a good practice to have this because it gives you good compile-time resolutions for the errors. For example, if you mark the interface as @FunctionalInterface and by mistake, you add any other method to that interface then the compiler will notify you that this is prohibited and you cannot add more than one method in the functional interface.

Done! That's all you need to know how to create a functional interface! Now, let's jump to the lambda expressions.

Lambda — is nothing but an implementation of the method which is there in the functional interface.

Let us modify the above example with functional interfaces and lambdas

@FunctionalInterface
interface Shape {
String getShape();
}

public class FunctionalInterfaceDemo {

public static void main(String[] args) {
Shape circle = () -> {
return "I am a Circle";
};
Shape square = () -> {
return "I am a Square";
};
System.out.println(processShapeObject(circle));
System.out.println(processShapeObject(square));
}

public static String processShapeObject(Shape shape) {
return shape.getShape();
}
}
OUTPUT -
I am a Circle
I am a Square

In the above example, we have annotated the interface with @FunctionalInterface and replace the anonymous class with a lambda expression. Here the lambda is simply re-implementing the method getShape(). Here processShapeObject() method remains intact and returns the shape of the object.

The intent of Java to introduce lambda is to give

  1. A flavor of functional programming for the developers. One can easily write a statement in a single line and use that in a program. This provides one more layer of abstraction for Anonymous classes.
  2. The lambdas are short-hand versions of the classes so it saves a lot of lines of code. It gives you an illusion of passing a function as a parameter.
System.out.println(processShapeObject(()->"I am a Triangle"));

Let us see the different syntax of writing lambda expressions.

@FunctionalInterface
interface Validator {
Boolean validate(Object o);
}
Validator validatorSimple = o -> o instanceof String;
Validator validatorWithBraces = (o) -> o instanceof String;
Validator validatorWithCurlyBraces = (o) -> {
if(o instanceof String) {
return true;
}
return false;
};

We are not looking here for the best programming practices, this is just to illustrate, in how many ways a lambda can be written. The main thing here is the operator ‘->’ (arrow). Left to this operator we define our parameters that need to be passed to the methods and to the right of the arrow is the implementation of the method. If there is only one parameter to the function we don't need any circular braces but if there no parameters or if there is more than one parameter then these parameters have to be wrapped up in the circular braces. Same thing with implementations. If there is a single line statement, we don't need curly braces, but if there are more then we need to provide the bunch of statements in curly braces. I will not go into the details of the syntax as my intent of writing this blog to get familiar with lambdas and functional interfaces. There are plenty of examples you will find on the internet and on JavaDocs which will make you familiar with different syntaxes for short-hand lambda expressions.

There is one more blog that will introduce you to basic and useful functional interfaces. Here is a link.

--

--