Java 8 functional interfaces, which are interfaces containing only one abstract method. The method itself is known as the functional method or Single Abstract Method (SAM). Examples include:
Predicate: Represents a predicate (boolean-valued function) of one argument. Contains only the test()
method, which evaluates the predicate on the given argument.
Supplier: Represents a supplier of results. Contains only the get()
method, which returns a result.
Consumer: Represents an operation that accepts a single input argument and returns no result. Contains only the accept()
method, which performs the operation on the given argument.
Function: Represents a function that accepts one argument and produces a result. Contains only the apply()
method, which applies the function to the given argument.
BiFunction: Represents a function that accepts two arguments and produces a result. Contains only the apply()
method, which applies the function to the given arguments.
Runnable: Represents a task that can be executed. Contains only the run()
method, which is where the task logic is defined.
Comparable: Represents objects that can be ordered. Contains only the compareTo()
method, which compares this object with the specified object for order.
ActionListener: Represents an action event listener. Contains only the actionPerformed()
method, which is invoked when an action occurs.
Callable: Represents a task that returns a result and may throw an exception. Contains only the call()
method, which executes the task and returns the result.
Table of Contents
Benefits of @FunctionalInterface Annotation
The @FunctionalInterface
annotation was introduced to explicitly mark an interface as a functional interface. It ensures that the interface has only one abstract method and allows additional default and static methods.
In a functional interface, besides the single abstract method (SAM), any number of default and static methods can also be defined. For instance:
interface ExampleInterface {
void method1(); // Abstract method
default void method2() {
System.out.println("Hello"); // Default method
}
}
Java 8 introduced the @FunctionalInterface
annotation to explicitly mark an interface as a functional interface:
@FunctionalInterface
interface ExampleInterface {
void method1();
}
It’s important to note that a functional interface can have only one abstract method. If there are more than one abstract methods, a compilation error occurs.
Functional Interface in java
Inheritance in Functional Interfaces
If an interface extends a functional interface and does not contain any abstract methods itself, it remains a functional interface. For example:
@FunctionalInterface
interface A {
void methodOne();
}
@FunctionalInterface
interface B extends A {
// Valid to extend and not add more abstract methods
}
However, if the child interface introduces any new abstract methods, it ceases to be a functional interface and using @FunctionalInterface
will result in a compilation error.
Lambda Expressions and Functional Interfaces:
Lambda expressions are used to invoke the functionality defined in functional interfaces. They provide a concise way to implement functional interfaces. For example:
Without Lambda Expression:
interface ExampleInterface {
void methodOne();
}
class Demo implements ExampleInterface {
public void methodOne() {
System.out.println("Method one execution");
}
public class Test {
public static void main(String[] args) {
ExampleInterface obj = new Demo();
obj.methodOne();
}
}
}
With Lambda Expression:
interface ExampleInterface {
void methodOne();
}
class Test {
public static void main(String[] args) {
ExampleInterface obj = () -> System.out.println("Method one execution");
obj.methodOne();
}
}
Advantages of Lambda Expressions:
- They reduce code length, improving readability.
- They simplify complex implementations of anonymous inner classes.
- They can be used wherever functional interfaces are applicable.
Anonymous Inner Classes vs Lambda Expressions:
Lambda expressions are often used to replace anonymous inner classes, reducing code length and complexity. For example:
With Anonymous Inner Class:
class Test {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("Child Thread");
}
}
});
t.start();
for (int i = 0; i < 10; i++) {
System.out.println("Main Thread");
}
}
}
With Lambda Expression:
class Test {
public static void main(String[] args) {
Thread t = new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println("Child Thread");
}
});
t.start();
for (int i = 0; i < 10; i++) {
System.out.println("Main Thread");
}
}
}
Differences between Anonymous Inner Classes and Lambda Expressions
Anonymous Inner Class | Lambda Expression |
A class without a name | A method without a name (anonymous function) |
Can extend concrete and abstract classes | Cannot extend concrete or abstract classes |
Can implement interfaces with any number of methods | Can only implement interfaces with a single abstract method |
Can declare instance variables | Cannot declare instance variables; variables are treated as final |
Has separate .class file generated at compilation | No separate .class file; converts into a private method |
Here is the link for the Java 8 quiz:
Click hereRelated Articles: