Java Interview Questions
Java
Web DevelopmentBackendQuestion 29
Explain the concept of functional interfaces.
Answer:
A functional interface in Java is an interface that contains exactly one abstract method. These interfaces are also known as Single Abstract Method (SAM) interfaces. Functional interfaces are designed to facilitate the use of lambda expressions and method references, which were introduced in Java 8. By having a single abstract method, they provide a clear target for lambda expressions, making the code more concise and readable.
Characteristics of Functional Interfaces
- Single Abstract Method: A functional interface has exactly one abstract method.
- Default and Static Methods: Functional interfaces can have any number of default and static methods, which do not affect the single abstract method requirement.
- @FunctionalInterface Annotation: While not mandatory, the
@FunctionalInterface
annotation can be used to explicitly declare a functional interface. This annotation is a form of documentation and helps the compiler enforce the contract by generating an error if the annotated interface does not meet the requirements of a functional interface.
Examples of Functional Interfaces
1. Predefined Functional Interfaces
The java.util.function
package provides several predefined functional interfaces:
-
Predicate<T>: Represents a boolean-valued function of one argument.
@FunctionalInterface public interface Predicate<T> { boolean test(T t); }
-
Consumer<T>: Represents an operation that accepts a single input argument and returns no result.
@FunctionalInterface public interface Consumer<T> { void accept(T t); }
-
Function<T, R>: Represents a function that accepts one argument and produces a result.
@FunctionalInterface public interface Function<T, R> { R apply(T t); }
-
Supplier<T>: Represents a supplier of results.
@FunctionalInterface public interface Supplier<T> { T get(); }
2. Custom Functional Interface
You can also define your own functional interfaces:
@FunctionalInterface
public interface MyFunctionalInterface {
void execute();
// You can add default and static methods
default void defaultMethod() {
System.out.println("This is a default method");
}
static void staticMethod() {
System.out.println("This is a static method");
}
}
Using Functional Interfaces with Lambda Expressions
Lambda expressions provide a concise way to implement the abstract method of a functional interface. Here are some examples:
Example 1: Using Predicate
import java.util.function.Predicate;
public class PredicateExample {
public static void main(String[] args) {
Predicate<String> isEmpty = s -> s.isEmpty();
System.out.println(isEmpty.test("")); // Output: true
System.out.println(isEmpty.test("Hello")); // Output: false
}
}
Example 2: Using Consumer
import java.util.function.Consumer;
public class ConsumerExample {
public static void main(String[] args) {
Consumer<String> print = s -> System.out.println(s);
print.accept("Hello, World!"); // Output: Hello, World!
}
}
Example 3: Using Function
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
Function<Integer, String> intToString = i -> Integer.toString(i);
System.out.println(intToString.apply(123)); // Output: 123
}
}
Example 4: Using Supplier
import java.util.function.Supplier;
public class SupplierExample {
public static void main(String[] args) {
Supplier<String> stringSupplier = () -> "Hello, Supplier!";
System.out.println(stringSupplier.get()); // Output: Hello, Supplier!
}
}
Benefits of Functional Interfaces
- Conciseness: Lambda expressions provide a more concise way to implement functional interfaces compared to anonymous inner classes.
- Readability: Code becomes more readable and expressive when using lambda expressions and method references.
- Flexibility: Functional interfaces can be used in a variety of contexts, such as passing behavior as parameters or defining operations on collections.
- Interoperability with Streams: Functional interfaces are heavily used in the Stream API, making it easier to perform complex data processing operations.
Conclusion
Functional interfaces in Java are a key feature that supports lambda expressions and method references, enabling a functional programming style. They provide a way to pass behavior as parameters, making the code more flexible, concise, and readable. By leveraging predefined functional interfaces and creating custom ones, you can write more expressive and maintainable code in Java.