Training Outcomes Within Your Budget!

We ensure quality, budget-alignment, and timely delivery by our expert instructors.

Share this Resource

Table of Contents

Functional Interface in Java

As a Java Developer, you’ve probably encountered situations where you wished for a more elegant way to handle repetitive logic. Well, Functional Interfaces in Java are here to rescue you! These nifty tools streamline your code by allowing you to define a single abstract method contract.  

This blog delves into the world of Functional Interfaces in Java. We’ll explore how they simplify your code, boost readability, and set the stage for using powerful features like lambda expressions and method references.

So buckle up, fellow coder! Let’s unlock a new level of development elegance together!

Table of Contents

1) What is a Functional Interface in Java?  

2) Ways to use Functional Interface

3) Functional Interface Annotation

4) Types of Functional Interface

5) Primitive Function Specialisations

6) Conclusion

What is a Functional Interface in Java? 

Java is an Object-oriented Programming Language, meaning everything revolves around classes and their objects. In Java, no function exists independently; functions are always part of classes or interfaces. To use a function, you need either the class or an object of that class to call it.

Functional Interfaces in Java enable the implementation of Functional Programming concepts. In Functional Programming, a function is treated as an independent entity capable of performing actions similar to variables, such as being passed as a parameter or returned by another function. Functions in Python exemplify functional programming.

Introduced in Java 8, a Functional Interface can contain only one abstract method but can include any number of static and default (non-abstract) methods.

Want to learn more advanced concepts in Java and become a better programmer? Sign up for the Java Programming course now. 

What is Lambda Expression? 

Lambda Expression was added in Java 8, which made Functional Interface possible. Earlier, you would have to create a class for every piece of functionality. Lambda Expressions allows you to pass or return from any method.  

Ideally, Lambda Expressions must be specific in expressing the functionality it has. 

Example 
 

public class LambdaExample
{
public static void main(String[] args)
{
Runnable r = () -> System.out.println("Hello, world!");
r.run();
}
}


This example creates a new 'Runnable' object using a Lambda expression. The 'Runnable' interface has only one abstract method called run(), which takes no arguments and returns no value.  

Instead of defining a separate class that implements the 'Runnable' interface, we can use a Lambda expression to directly create a new instance of the 'Runnable' interface.   

This Lambda Expression is a short function that takes no arguments and prints "Hello, world!" to the console. 

() -> System.out.println("Hello, world!")  

Finally, it calls the run() method on the 'Runnable' object to execute the Lambda expression and print the message "Hello, world!" to the console. 

What is Abstract Method? 

An abstract method is a type of method that is only declared but not defined in a class. It has no implementation details and behaves like a placeholder for any subclass declaring the abstract method. The abstract method ensures that any subclass of the declaring class implementing the method has a common behaviour across all subclasses. 

Example 

Let's say you have an abstract class called 'Animal'. 'eat()', 'sleep()', and 'move()' can be a set of common methods and properties that all animals share in the class 'Animal'. However, the 'Animal' class doesn't provide any implementation details for these methods; instead, it simply declares them abstract. 
 

public abstract class Animal
{
public abstract void eat();
public abstract void sleep();
public abstract void move();
}


By defining these methods as abstract, the 'Animal' class declares that any subclass of 'Animal' must implement these methods. For example, you might have a subclass called 'Dog' that extends 'Animal'. This class would need to implement the 'eat()', 'sleep()', and 'move()' methods to be a valid subclass of 'Animal'
 

public class Dog extends Animal
{
public void eat()
{
System.out.println("The dog is eating");
}
public void sleep()
{
System.out.println("The dog is sleeping");
}
public void move()
{
System.out.println("The dog is running"); }
}


By using the required methods in the 'Dog' subclass, you can be sure that any instance of the 'Dog' class will have the required behaviour of an animal. 
 

java Training
 

Ways to use Functional Interface 

Now that you know Java Functional Interface, it's time to learn how to use them. There are two ways to use Functional Interface. One method uses the Lambda expression, and another implements the Interface (overriding the abstract method). 

Using Lambda Expression to use Functional Interface 

Lambda expressions in Java are similar to regular methods but offer a more concise, readable way to write code. Here are key points to remember when using lambda expressions to implement a Functional Interface:

a) Always annotate the interface declaration with @FunctionalInterface.

b) A lambda expression can be passed as a parameter to a method or returned as a value, functioning like a regular function.

c) A Functional Interface can only contain one abstract method; otherwise, the compiler will throw an "Unexpected @FunctionalInterface annotation" error.

d) You don't need to specify the abstract keyword before the method, as all methods in a Functional Interface are implicitly abstract.

For example, to create a Functional Interface that calculates the area of a rectangle, you can define the interface as follows:
 

@FunctionalInterface 

public interface RectangleAreaCalculator
{
public double calculateArea(double length, double width);
}


After defining the Functional Interface, you can implement its single abstract method using Lamba expression. Let's say you want to implement a 'RectangleAreaCalculator' interface; you can do it like this: 

RectangleAreaCalculator calculator = (length, width) -> length * width;

This example uses the lambda expression '(length, width) -> length * width' to take two parameters as length and width and returns the product of it. The lambda expression is then assigned to 'RectangleAreaCalculator', the Functional Interface implemented earlier.

When you are done implementing the Functional Interface with a Lambda expression, you can use it like any other object in your code. You can use the 'calculator' variable to calculate the area of a rectangle like this.

double area = calculator.calculateArea(5.0, 10.0); // area is 50.0

In this case, the 'calculateArea' is the method, and the 'calculator' is the object with arguments '5.0' and '10.0'. This method uses a Lambda expression to calculate the area of the rectangle to the assigned 'area' variable. 

Using Functional Interface by implementing the Interface (overriding the abstract method)

Using the Functional Interface implements the Interface in the class and overrides the abstract method. To call the method, you have to create the object of the class and then use the syntax obj.AbstractMethod().

First, you must define the Functional Interface with a single abstract method like before. Let's take the same example of calculating the area of a rectangle. The first step of implementing the Functional Interface with the abstract method will remain the same. 
 

@FunctionalInterface 
public interface RectangleAreaCalculator
{
public double calculateArea(double length, double width);
}


Next, you must create a class that implements the Functional Interface and then overrides the abstract method. This is where the code differs from the method used earlier. 
 

public class CalculateRectangleArea implements RectangleArea
{
@Override
public double calculate(double length, double width)
{
return length * width;
}
}


Here, the 'CalculateRectangleArea' class implements the method 'calculate' of the 'RectangleArea' interface that takes the length and width to return the area value.  

Now that you have implemented the Functional Interface by overriding the abstract method, you can use it like any object in the code like this. 

RectangleArea areaCalculator = new CalculateRectangleArea(); 

double length = 5.0; 

double width = 3.0; 

double area = areaCalculator.calculate(length, width); 

System.out.println("The area of the rectangle is: " + area); 

Here, an instance of the 'CalculateRectangleArea' class is created and assigned to a variable 'RectangleArea', which is the Functional Interface. The method calculates the rectangle area and returns it as a double value stored in the 'area' variable.

Functional Interface with Methods of the Object Class

A Functional Interface in Java can include methods from the Object class. Here's an example demonstrating this concept:

@FunctionalInterface
interface ObjectClassMethods {
// Abstract method
int abstractMethod(int val);
// Methods from the Object class
int hashCode();
String toString();
boolean equals(Object obj);
}
 

In the interface above, hashCode(), toString(), and equals() are methods from the Object class. We can include any number of methods from the Object class in a Functional Interface, and they do not require an implementation within the interface.

Functional Interface with Multiple Default and Static Methods

Let's look at an example of a Functional Interface in Java that includes default and static methods:

@FunctionalInterface
interface StaticandDefaultMethods {
    // Abstract method
    int square(int x);
    // Default methods
    default int add(int a, int b) {
        return a + b;
    }
    default int sub(int a, int b) {
        return a - b;
    }
    // Static methods
    static int multiply(int a, int b) {
        return a * b;
    }
    static int divide(int a, int b) {
        return a / b;
    }
}
// Public class
public class Test implements StaticandDefaultMethods {
    public static void main(String[] args) {
        int a = 8;
        int b = 6;
        // Object of Test class
        Test t = new Test();
        // Default methods called using class object
        int add = t.add(a, b);
        int sub = t.sub(a, b);
        // Static methods called directly by the interface name
        int mul = StaticandDefaultMethods.multiply(a, b);
        int div = StaticandDefaultMethods.divide(a, b);
    }
    // Abstract method implementation
    @Override
    public int square(int x) {
        return x * x;
    }
}

In this example, square is an abstract method, add and sub are default methods, and multiply and divide are static methods. We override the square() method in the Test class. The default methods add() and sub() can be overridden in the Test class and are called using an instance of the Test class. The static methods multiply() and divide() are called using the interface name.

Functional Interface Extending a Non-Functional Interface

A Functional Interface in Java can extend other interfaces. The extends keyword is used to inherit methods from a parent interface. The parent interface must not be a Functional Interface and should not contain any abstract methods. The child interface (Functional Interface) can have a single abstract method and multiple default and static methods.

Consider a scenario with a BookStore interface and a Library interface as a Functional Interface.

interface BookStore {
int sell();
int buy();
List customers();
// boolean issue_book(); // Uncommenting this will cause a compilation error
}
@FunctionalInterface
interface Library extends BookStore {
boolean issue_book();
}

The compiler throws an exception because the BookStore interface has three abstract methods. Therefore, the Library interface cannot extend BookStore.

Learn to build applications from scratch with our Introduction To Java EE Training.   

Functional Interface Annotation

The @FunctionalInterface annotation ensures that a functional interface cannot have more than one abstract method. If more than one abstract method is present, the compiler will flag an "Unexpected @FunctionalInterface annotation" message. However, using this annotation is not mandatory.

Here’s an implementation demonstrating the concept:

// Java program to demonstrate lambda expressions to
// implement a user-defined functional interface.
@FunctionalInterface
interface Greeting {
String sayHello(String name);
}
class Test {
public static void main(String[] args) {
// Lambda expression to define the sayHello method
Greeting greeting = (String name) -> "Hello, " + name;
// Parameter passed and return type must match the prototype
String result = greeting.sayHello("John");
System.out.println(result);
}
}

Output:

Hello, John

In this example, Greeting is a functional interface with a single abstract method sayHello. The lambda expression (String name) -> "Hello, " + name implements the sayHello method. The result is printed by calling greeting.sayHello("John").

Types of Functional Interface 


Functional Interfaces

These are the four common types of Functional Interface used in Java 

a) Predicate 

b) Consumer 

c) Supplier 

d) Function 

Predicate 

This type of Functional Interface represents a function that takes in an argument and returns a Boolean value based on a condition. For example, it can check whether a given number is even or odd. 

Here is an example of a Predicate Functional Interface 

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class PredicateExample
{
public static void main(String[] args)
{
List numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);
Predicate isEven = n -> n % 2 == 0;
List oddNumbers = numbers.stream()
.filter(isEven.negate())
.toList();
System.out.println("Odd numbers: " + oddNumbers);
}
}

Here, the 'Predicate' Functional Interface named 'isEven' checks whether the given integer is even by using the modulo operator to check whether the remainder is zero after dividing it by two. Further, it uses the 'Stream' class' 'filter()' method to create a list of odd numbers by negating the' isEven' predicate using the 'negate()' method. 

Consumer 

This is a type of Functional Interface that takes in an argument but does not return any value. For example, you can print out a list of names. 

Here is an example of a consumer Functional Interface. 
 

import java.util.function.Consumer;
public class ExampleConsumer
{
public static void main(String[] args)
{
Consumer printLength = (String str) -> System.out.println("Length of string: " + str.length());
printLength.accept("Hello, world!"); // Output: Length of string: 13
}
}


Here, the 'Consumer' Functional Interface called 'printlength' that takes in a 'string' and prints it. The Lambda expression '(String str) -> System.out.println("Length of string: " + str.length())’ defines the behavior of the Consumer interface. Next, the 'accept method' of the 'Consumer' interface takes in the string "Hello, world!" as an argument, which results in the output "Length of string: 13". 

Supplier 

Supplier Functional Interface is the type which doesn't take in any arguments but returns a value. For example, you can use the Supplier to generate a random number or alphabet.

Here's an example of a Supplier Functional Interface 

import java.util.function.Supplier;
public class ExampleSupplier
{
public static void main(String[] args)
{
Supplier randomInt = () -> (int) (Math.random() * 100);
System.out.println("Random number: " + randomInt.get());
}
}


Here, the 'Supplier< Integer' Functional Interface called the 'randomInt' returns a random integer between 0 and 100. The lambda expression used here defines the behaviour of the 'Supplier' interface. Using 'get' method, a random integer is generated as output. 

Function 

The function is a type of Functional Interface that returns a value after taking in a single argument. For example, you can Function to convert a string into an integer. 

Here’s an example of function Functional Interface:  
 

import java.util.function.Function;
public class ExampleFunction
{
public static void main(String[] args)
{
Function square = (Integer x) -> x * x;
System.out.println("Square of 5: " + square.apply(5)); // Output: Square of 5: 25
}
}


Here, the 'FunctionFunctional Interface calls the 'square' that takes in an 'Integer' and returns its square value. The lambda expression used here defines the behaviour of the 'Function' interface. The 'apply' method of the interface takes in '5' as an argument and returns the square value. 

Some built-in Functional Interfaces 

Post Java 8, many interfaces were converted into Functional Interfaces, and these are annotated with @FunctionalInterface. These interfaces are given below. 

a) Runnable: Contains only the run() method 

b) Comparable: Contains only the compareTo() method 

c) ActionListener: Contains only the actionPerformed() method 

d) Callable: Contains only the call() method

Primitive Function Specialisations

Primitive data types cannot be directly used as parameters for generic type arguments. For example, we cannot pass int, double, or float instead of T or R in R apply(T t) of Function.

In functional interfaces and Streams, certain classes are designed specifically to operate with int, long, and double without boxing them into wrapper classes. This is known as primitive specialisation.

There are various versions of the Function interface tailored for commonly used primitive data types, both as argument and return types:

a) IntFunction, LongFunction, DoubleFunction: The argument type is specified in the function name, and the return type is parameterised.

b) ToIntFunction, ToLongFunction, ToDoubleFunction: The return type is specified in the function name, and the argument type is parameterised.

c) DoubleToIntFunction, DoubleToLongFunction, IntToDoubleFunction, IntToLongFunction, LongToIntFunction, LongToDoubleFunction: Both the argument and return types are specified in the function name.

Improve your understanding of JavaScript by signing up for our JavaScript for Beginners Course now!   

Conclusion 

To sum it up, Java Functional Interface in Java enables programmers to write code more concisely and modularly. The best part about the Functional Interface is that it significantly reduces bloat in the code, making debugging easier. There are a lot of predefined Functional Interface in Java to implement them using method references and lambda expressions, and you can use your own custom interfaces. 

Want to learn more advanced concepts in Java and become a better programmer? Sign up for our comprehensive Java Programming Course today!

Frequently Asked Questions

What is Encapsulation in Java? faq-arrow

Encapsulation in Java is a mechanism that binds the data (variables) and methods (functions) acting on the data into a single unit known as a class. It restricts access to some of the object's components, promoting data hiding and protection, ensuring that the internal implementation details are hidden from the outside world.

What are the Rules for Functional Interface? faq-arrow

Functional Interfaces in Java have three rules:

a) It must have only one abstract method.

b) It can have multiple default or static methods.

c) It must be annotated with the @FunctionalInterface annotation to ensure that it only has one abstract method, making it clear for functional programming and compatibility with lambda expressions.
 

What is Knowledge Pass, and how does it work? faq-arrow

The Knowledge Academy’s Knowledge Pass, a prepaid voucher, adds another layer of flexibility, allowing course bookings over a 12-month period. Join us on a journey where education knows no bounds.

What are related Courses and blogs provided by The Knowledge Academy? faq-arrow

The Knowledge Academy offers various Java Training including Java Programming, JavaScript for Beginners and Java Swing Development Training. These courses cater to different skill levels, providing comprehensive insights into How to Become a Java Developer.

Our Programming and DevOps blogs cover a range of topics related to Java, offering valuable resources, best practices, and industry insights. Whether you are a beginner or looking to advance your Java Programming skills, The Knowledge Academy's diverse courses and informative blogs have you covered.
 

What are the other resources provided by The Knowledge Academy? faq-arrow

The Knowledge Academy takes global learning to new heights, offering over 30,000 online courses across 490+ locations in 220 countries. This expansive reach ensures accessibility and convenience for learners worldwide.

Alongside our diverse Online Course Catalogue, encompassing 17 major categories, we go the extra mile by providing a plethora of free educational Online Resources like News updates, Blogs, videos, webinars, and interview questions. Tailoring learning experiences further, professionals can maximise value with customisable Course Bundles of TKA.
 

Upcoming Programming & DevOps Resources Batches & Dates

Date

building Java Programming

Get A Quote

WHO WILL BE FUNDING THE COURSE?

cross

OUR BIGGEST SPRING SALE!

Special Discounts

red-starWHO WILL BE FUNDING THE COURSE?

close

close

Thank you for your enquiry!

One of our training experts will be in touch shortly to go over your training requirements.

close

close

Press esc to close

close close

Back to course information

Thank you for your enquiry!

One of our training experts will be in touch shortly to go overy your training requirements.

close close

Thank you for your enquiry!

One of our training experts will be in touch shortly to go over your training requirements.