Java Functional Interface Interview Questions and Answers

In this article, we will discuss some important and frequently asked Java 8 Functional Interface Interview Questions and Answers.

Check out Java 8 Interview Questions

1. What is a functional interface?

A functional interface in Java is an interface that has exactly one abstract method. Since functional interfaces have only one abstract method, they can represent a single functionality that can be implemented by a lambda expression, a method reference, or an anonymous class. 

Introduced in Java 8, functional interfaces are a key feature that enables functional programming concepts within the language. They allow you to use simple expressions to represent instances of anonymous classes that implement the interface, making code more concise and readable. 

Key points about functional interfaces: 

Single Abstract Method (SAM): A functional interface must contain exactly one abstract method. It can have more than one non-abstract method (default or static methods), but only one abstract method is allowed. 
@FunctionalInterface Annotation: While it's not required, it's good practice to annotate a functional interface with @FunctionalInterface. This annotation ensures that the interface meets the requirements of a functional interface at compile time. If you try to add a second abstract method, the compiler will raise an error. 
Built-in Functional Interfaces: Java 8 introduced several built-in functional interfaces within the java.util.function package. Some common ones include Predicate<T>, Function<T, R>, Supplier<T>, Consumer<T>, and others. 
Lambda Expressions: Since functional interfaces have only one abstract method, you can use lambda expressions to provide the implementation of that method directly within the code where it's needed.

Example:

@FunctionalInterface
public interface MyFunctionalInterface {
    void execute();
}

// Using a lambda expression to implement the functional interface
MyFunctionalInterface implementation = () -> System.out.println("Executing...");
implementation.execute(); // Output: Executing...

2. Is it possible to define our own Functional Interface? What is @FunctionalInterface? What are the rules to define a Functional Interface?

Yes, it is possible to define your own functional interface in Java, and the @FunctionalInterface annotation is often used to mark an interface as a functional interface. 

What is @FunctionalInterface? 

The @FunctionalInterface annotation is used to indicate that an interface is intended to be a functional interface. While it is not mandatory to use this annotation when defining a functional interface, it's a good practice because it makes the intention clear and allows the compiler to generate an error if the annotated interface does not satisfy the conditions of a functional interface. 

Rules to Define a Functional Interface 

Exactly One Abstract Method: The functional interface must contain exactly one abstract method. Having more or fewer abstract methods will violate the functional interface contract. 

Any Number of Default and Static Methods: You can have any number of default or static methods in the functional interface. 

@FunctionalInterface Annotation (Optional but Recommended): Using the @FunctionalInterface annotation helps in indicating the purpose of the interface and ensures a compile-time check. 

Inheritance: A functional interface can extend another interface only if it does not have any abstract method itself. 

Example of a Custom Functional Interface

@FunctionalInterface
interface MyFunctionalInterface {
    // Single abstract method
    void execute();
    
    // Default method
    default void defaultMethod() {
        System.out.println("Default method");
    }
    
    // Static method
    static void staticMethod() {
        System.out.println("Static method");
    }
}
Read more at Java 8 Functional Interfaces with Examples.

3. Name some of the functional interfaces in the standard library

In Java 8, there are a lot of functional interfaces introduced in the java.util.function package and the more common ones include but are not limited to:
  1. Function<T, R>: Represents a function that takes an argument of type T and returns a result of type R. 
  2. Consumer<T>: Represents an operation that takes a single input argument of type T and returns no result (performs a side effect). 
  3. Supplier<T>: Represents a supplier of results, taking no arguments but providing a result of type T.
  4. Predicate<T>: Represents a boolean-valued function of one argument of type T. Commonly used for filtering or matching. 
  5. UnaryOperator<T>: Represents a function that takes a single argument of type T and returns a result of the same type. It extends Function<T, T>. 
  6. BinaryOperator<T>: Represents a function that takes two arguments of type T and returns a result of the same type. It extends BiFunction<T, T, T>. 
  7. BiFunction<T, U, R>: Represents a function that takes two arguments of types T and U and returns a result of type R. 
  8. BiConsumer<T, U>: Represents an operation that takes two input arguments of types T and U and returns no result. 
  9. BiPredicate<T, U>: Represents a boolean-valued function that takes two arguments of types T and U. 
  10. ToIntFunction<T>, ToLongFunction<T>, and ToDoubleFunction<T>: Represents functions that take an argument of type T and return a primitive int, long, or double value, respectively. 
  11. IntFunction<R>, LongFunction<R>, DoubleFunction<R>: Represents functions that take a primitive int, long, or double value and return a result of type R. 
These functional interfaces are part of the java.util.function package, and they can be used with lambda expressions, method references, or anonymous inner classes. They greatly enhance the ability to write concise and functional-style code in Java.

4. What Is the Difference Between a Normal and Functional Interface in Java?

In Java, the distinction between a normal interface and a functional interface is mainly related to the number of abstract methods they contain and their intended usage. 
Here's a breakdown of the differences: 

Normal Interface: 

Abstract Methods: A normal interface can have more than one abstract method. There are no constraints on the number of abstract methods it can declare. 

Static and Default Methods: It may contain static methods and default methods with implementations. 

Purpose: A normal interface serves the traditional role of defining a contract that implementing classes must follow. It's used for multiple inheritance and polymorphism. 

Usage with Lambda Expressions: You cannot use normal interfaces (with more than one abstract method) with lambda expressions. 

Functional Interface: 

Abstract Methods: A functional interface has exactly one abstract method. This abstract method is called the functional method. 

Static and Default Methods: Like normal interfaces, functional interfaces can also contain static and default methods with implementations. 

Purpose: Functional interfaces are designed to facilitate functional programming in Java, allowing methods to be used as first-class citizens, passed as arguments, and returned as values. 

Usage with Lambda Expressions: Functional interfaces can be implemented using lambda expressions, providing a concise way to implement the single abstract method.

Annotation: Although not mandatory, a functional interface can be annotated with @FunctionalInterface. This annotation ensures that the interface will not compile if more than one abstract method is declared.

5. What is a Function interface?

The Function is a functional interface introduced in Java 8; it takes an argument (object of type T) and returns an object (object of type R). The argument and output can be of different types.

This is the internal implementation of the Function interface:
@FunctionalInterface
public interface Function<T, R> {
      R apply(T t);
}
  • T – Type of the input to the function.
  • R – Type of the result of the function.

Example:

        Function < String, Integer > function = (t) -> t.length();
        System.out.println(function.apply("Ramesh"));
Output:
6

6. What is a Predicate interface?

The Predicate is a functional interface that can be used as an assignment target for a lambda expression.

The Predicate interface represents an operation that takes a single input and returns a boolean value.

This is the internal implementation of the Predicate interface:
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}
T – Type of the input to the predicate

Example:

        Predicate < Integer > predicate = (t) -> {
            if (t % 2 == 0) {
                return true;
            } else {
                return false;
            }
        };

        System.out.println(predicate.test(10));
Output:
true

Read more at Java 8 Predicate interface Example 

7. What is the Consumer interface?

A Consumer is a functional interface in JDK 8, which represents an operation that accepts a single input argument and returns no result.

This is the internal implementation of the Consumer interface:
@FunctionalInterface
public interface Consumer < T > {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

Example:

        Consumer < String > consumer = (t) -> System.out.println(t);
        consumer.accept("Ramesh");
Output:
Ramesh

Read more at Java 8 Consumer Interface Example

8. What is the Supplier interface?

The Supplier is a functional interface that represents an operation that takes no argument and returns a result.

This is the internal implementation of the Supplier interface:
@FunctionalInterface
public interface Supplier<T> {
    T get();
}
Example:
        Supplier < LocalDateTime > supplier = () -> LocalDateTime.now();
        System.out.println(supplier.get());
Output:
2020-04-30T11:32:51.628

9. What is the BiFunction interface?

The BiFunction interface is a functional interface that represents a function that takes two arguments of different types and produces a result of another type. 

This is the internal implementation of the BiFunction interface:
@FunctionalInterface
public interface BiFunction<T, U, R> {
     R apply(T t, U u); // Other default and static methods
     // ...
}

Example:

// And with a lambda expression:
        BiFunction < Integer, Integer, Integer > biFunction = (t, u) -> (t + u);

        BiFunction < Integer, Integer, Integer > substraction = (t, u) -> (t - u);

        BiFunction < Integer, Integer, Integer > multiplication = (t, u) -> (t * u);

        BiFunction < Integer, Integer, Integer > division = (t, u) -> (t / u);

        System.out.println(biFunction.apply(10, 20));
        System.out.println(substraction.apply(200, 100));

        System.out.println(multiplication.apply(200, 100));

        System.out.println(division.apply(200, 100));
Output:
30
900
20000
2

Read more at Java 8 BiFunction Example

Related Java Interview Articles

Comments