2
2
.
.
5
5
.
.
2
2
L
L
a
a
m
m
b
b
d
d
a
a
s
s
I
I
n
n
f
f
o
o
Lambda Expression is simpler Syntax to create Instance of Anonymous Inner Class that Implements Functional Interface
so that this Class Instance can then be used as a Parameter to a Function
so that Function can then call the Method wrapped inside that Class Instance
Sending Function as Parameter
class Test {
//MAIN FUNCTION.
public static void main(String[] args) {
//CREATE INSTANCE OF ANONYMOUS INNER CLASS THAT IMPLEMENTS FUNCTIONAL INTERFACE.
MyInterface classInstance = (name, age) -> { return(name + " is " + age + " years old"); };
//CALL METHOD WITH INSTANCE AS PARAMETER.
displayMessage(classInstance);
}
//FUNCTION THAT EXCEPTS INSTANCE OF THE CLASS THAT IMPLEMENTS FUNCTIONAL INTERFACE.
public static void displayMessage(MyInterface myInterface) {
String result = myInterface.greet("John", 20); //Call Method that is wraped inside Instance Parameter
System.out.println(result);
}
}
//FUNCTIONAL INTERFACE MUST HAVE SINGLE ABSTRACT METHOD.
@FunctionalInterface
interface MyInterface {
public abstract String greet(String name, int age);
}
Output
John is 20 years old
T
T
h
h
e
e
o
o
r
r
y
y
Functional Programming is ability to send Functions as Parameters to other Functions (usually as asynch callback handler).
In JAVA 8 this is achieved by sending Instance of Anonymous Inner Class that Implements Functional Interface.
Lambda Expression is just an alternative Syntax to create such Instance and specify custom Function Body.
F
F
u
u
n
n
c
c
t
t
i
i
o
o
n
n
a
a
l
l
P
P
r
r
o
o
g
g
r
r
a
a
m
m
m
m
i
i
n
n
g
g
One of main characteristics of Functional Programming is to be able to send functions as parameters to other functions.
Unfortunately in JAVA Functions are not First Class Citizens [R] which means they can't live on their own.
This also means that it is not possible to send them as parameters to other Functions and Functions can't return them.
In JAVA Functions can only leave inside Classes (which is why they are always referred as Methods).
So JAVA is using existing functionality, in the form of Functional Interface, to create workaround to achieves this.
In modern languages (like Kotlin and Swift) you simply specify which Function Data Type Variable can hold.
This is known as specifying Function Signature and includes Return Data Type and Data Types of Input Parameters.
Then when you assign Lambda Expression to such Variable Compiler can check if Lambda Expression
has the same number of Input Parameters as specified by the Function Signature
returns the same Data Type as specified by the Function Signature
uses Input Parameters correctly based on their Data Types as specified by the Function Signature
Test.swift
In Java Functions can't exist on their own, they are not First Class Citizens and there is no Function Data Type.
Instead every Function needs to be defined inside the Class and then it is called a Method.
So in Java you declare Functional Interface (interface with a single Functional).
So this is how you specify Method Signature Function's Return Data Type and Data Types of Input Parameters.
And then you use this Interface when declaring a Variable that is supposed to hold a Function.
Then when you assign Lambda Expression to such Variable Compiler can check if Lambda Expression
has the same number of Input Parameters as specified by the Functional Interface
returns the same Data Type as specified by the Functional Interface
uses Input Parameters correctly based on their Data Types as specified by the Functional Interface
In Java you can't specify Data Types of Lambda Input Parameters inside the Lambda Expression itself.
This is one reason you have to tell Compiler which Functional Interface is being used.
So that Compiler can check if Input Parameters are used correctly inside Lambda Expression.
Store Lambda Expression into a Variable
class Test {
public static void main(String[] args) {
//CREATE INSTANCE OF ANONYMOUS INNER CLASS THAT IMPLEMENTS FUNCTIONAL INTERFACE.
MyInterface classInstance = (name, age) -> { return(name + " is " + age + " years old"); };
}
}
//FUNCTIONAL INTERFACE MUST HAVE SINGLE ABSTRACT METHOD.
@FunctionalInterface
interface MyInterface {
public abstract String greet(String name, int age);
}
Send Lambda Expression as Function Parameter
class Test {
//MAIN FUNCTION.
public static void main(String[] args) {
//CREATE INSTANCE OF ANONYMOUS INNER CLASS THAT IMPLEMENTS FUNCTIONAL INTERFACE.
MyInterface classInstance = (name, age) -> { return(name + " is " + age + " years old"); };
//CALL METHOD WITH INSTANCE AS PARAMETER.
displayMessage(classInstance);
}
//FUNCTION THAT EXCEPTS INSTANCE OF ANONYMOUS INNER CLASS THAT IMPLEMENTS FUNCTIONAL INTERFACE.
public static void displayMessage(MyInterface myInterface) {
String result = myInterface.greet("John", 20); //Call Method that is wrapped inside Instance Parameter
System.out.println(result);
}
}
//FUNCTIONAL INTERFACE MUST HAVE SINGLE ABSTRACT METHOD.
@FunctionalInterface
interface MyInterface {
public abstract String greet(String name, int age);
}
F
F
u
u
n
n
c
c
t
t
i
i
o
o
n
n
a
a
l
l
I
I
n
n
t
t
e
e
r
r
f
f
a
a
c
c
e
e
Instead of sending actual Function we are sending Instance of a Class that Implements Functional Interface.
To do that we need to perform following steps
declare Functional Interface (Interface with a single Abstract Method that has no body)
declare Class that Implements this Interface (since in JAVA you can't create Interface Instance to pass around)
inside Class implement that Abstract Method (since for all Abstract Methods Class needs to provide body)
create Instance of that Class (since you can't send Class as Function Input Parameter)
send this Instance as a Parameter to a Function (since Instances can be sent as Function Input Parameters)
since Functional Interface has one function, method that gets this Instance as parameter knows which function to call
It is called Functional because it is used to create multiple Functions that have the same Signature but different body.
Signature means specific combination of Return Value & Input Parameters (as declared by the Abstract Method).
When you create Instance of Class that Implements Functional Interface you can specify new body for Abstract Method.
Functional Interface is declared like any other Interface using Keyword Interface followed by the Name and Body.
But it must contain only a single Abstract Method.
Annotation @FunctionalInterface is optional. It simply tells Compiler that our intention is to create Functional Interface.
This way if we accidently declare more than one Abstract Method, or if Method is not Abstract, Compiler will warn us.
Declare Functional Interface
//FUNCTIONAL INTERFACE MUST HAVE SINGLE ABSTRACT METHOD.
@FunctionalInterface
interface MyInterface {
public abstract String greet(String name, int age);
}
A
A
n
n
o
o
n
n
y
y
m
m
o
o
u
u
s
s
I
I
n
n
n
n
e
e
r
r
C
C
l
l
a
a
s
s
s
s
Functional Interface will be used to create Instance of Anonymous Inner Class that Implements Functional Interface.
This Instance is then used as a Input Parameter to a Function which can call the Method within the Instance.
Remember that the whole point is to be able to pass Function as Input Parameter to another Function (shown in yellow).
Annotation @Override is optional. It simply tells Compiler that our intention is to override an existing Interface Method.
This way if we accidently specify different Name of different combination of Return Value & Input Parameters, Compiler
will warn us.
Sending Instance as Function Parameter
class Test {
//MAIN FUNCTION.
public static void main(String[] args) {
//CREATE INSTANCE OF ANONYMOUS INNER CLASS THAT IMPLEMENTS INTERFACE.
MyInterface classInstance = new MyInterface() {
@Override
public String greet(String name, int age) {
return(name + " is " + age + " years old");
}
};
//CALL METHOD THAT ACCEPTS INSTANCE AS PARAMETER (FUNCTION IS WRAPED INSIDE THE INSTANCE).
displayMessage(classInstance);
}
//FUNCTION THAT EXCEPTS INSTANCE OF THE CLASS THAT IMPLEMENTS FUNCTIONALINTERFACE.
public static void displayMessage(MyInterface myInterface) {
String result = myInterface.greet("John", 20);
System.out.println(result);
}
}
//FUNCTIONAL INTERFACE MUST HAVE SINGLE ABSTRACT METHOD.
@FunctionalInterface
interface MyInterface {
public abstract String greet(String name, int age);
}
In the above example first we create Instance of the Inner Class and then use it as Input Parameter into Method.
But it is also possible to use Syntax for creating Instance of Inner Class at the place of the Parameter (as shown below).
Crating Instance at the place of the Input Parameter (When Method is called)
displayMessage(new MyInterface() {
@Override
public String greet(String name, int age) {
return(name + " is " + age + " years old");
}
});
L
L
a
a
m
m
b
b
d
d
a
a
E
E
x
x
p
p
r
r
e
e
s
s
s
s
i
i
o
o
n
n
Lambda Expression is just alternative Syntax for creating Instance of the Inner Class that Implements Functional Interface.
It is shorter but in the background it is transformed into the same thing. Following examples show how to create Instance
of the Inner Class that Implements Functional Interface without and with Lambda Expression.
Compiler knows Data Types of Input Parameters & Return Value since we have specified that Variable is of Data Type
MyInterface Functional Interface (it can hold instance of a Class that implements this Interface).
Without Lambda Expression (As used in the previous example)
//CREATE INSTANCE OF ANONYMOUS INNER CLASS THAT IMPLEMENTS FUNCTIONAL INTERFACE.
MyInterface classInstance = new MyInterface() {
@Override
public String greet(String name, int age) {
return(name + " is " + age + " years old");
}
};
With Lambda Expression (Shorter Syntax. Data Types are implied from the Functional Interface.)
//CREATE INSTANCE OF ANONYMOUS INNER CLASS THAT IMPLEMENTS FUNCTIONAL INTERFACE.
MyInterface classInstance = (name, age) -> { return(name + " is " + age + " years old"); };
And if Lambda Expression is used directly at the place of Input Parameter, Compiler uses Data Type of the Input
Parameter (as defined during Method declaration) to figure out proper Data Types of Input Parameters and Return Value
(which should be as declared by the single Abstract Method inside that Functional Interface).
Using Lambda Expression at the place of the Input Parameter (When Method is called)
//DECLARE METHOD.
public static void displayMessage(MyInterface myInterface) { ... }
//CALL METHOD.
displayMessage((name, age) -> { return(name + " is " + age + " years old"); });