Functional Interfaces in Java

  1. 1. A Functional Interface is an interface that has only one abstract method. They can have only one functionality to exhibit
  2. 2. Note that instances of functional interfaces can be created with the help of lambda expressions, method references, constructor references, or anonymous classes.
  3. 3. A functional interface can have any number of default methods.
  4. 4. Runnable, ActionListener, Consumer, and Comparable are some examples of functional interfaces.
  5. 5. A functional interface can also contain any number of static methods

Java provides predefined functional interfaces to deal with functional programming by using lambda and method references.

Example1:
                      
                        package com.java.session.seventeen;

                        @FunctionalInterface
                        public interface FunctionalInterfaceDemo {
                            int additionOfTwoNumber(int value1, int value2);
                        }

                        package com.java.session.seventeen;

                        public class FunctionalInterfaceExample {
                            
                            public static void main(String[] args) {
                                FunctionalInterfaceDemo functionalInterfaceDemo = (v1, v2) -> v1 + v2;
                                int result = functionalInterfaceDemo.additionOfTwoNumber(10, 50);
                                System.out.println(result);
                            }
                        }
                      
                    

Default Methods

Before Java 8, interfaces could have only abstract methods. The implementation of these methods has to be provided in a separate class. So, if a new method is to be added in an interface, then its implementation code has to be provided in the class implementing the same interface. To overcome this issue, Java 8 has introduced the concept of default methods which allow the interfaces to have methods with implementation without affecting the classes that implement the interface.

Default methods only allow to use inside the interfaces, default is a keyword which is used to declare to a method. If a method delcare with the keyword default then we call it as a default method.

                      
                        package com.java.session.seventeen;

                        @FunctionalInterface
                        public interface FunctionalInterfaceDemo {
                            int additionOfTwoNumber(int value1, int value2);

                            default String printResult(int result) {
                                return "Result is - "+result;
                            }
                        }

                        package com.java.session.seventeen;

                        public class FunctionalInterfaceExample {
                            public static void main(String[] args) {
                                FunctionalInterfaceDemo functionalInterfaceDemo = (v1, v2) -> v1 + v2;
                                int res = functionalInterfaceDemo.additionOfTwoNumber(10, 50);
                                System.out.println(res);
                                String finalResult = functionalInterfaceDemo.printResult(res);
                                System.out.println(finalResult);
                            }
                        }

                      
                    

Java 8 — Predefined Functional Interfaces:

1. Supplier<T>:

  1. Abstract method: T get()
  2. This represents a supplier of results, providing a value without taking any input.
  3. It is commonly used for lazy initialization or generating values.
                          
                            //Generates a random integer between 0 and 99
                            Supplier<Integer> randomNumberSupplier = () -> (int) (Math.random() * 100);
                            int randomValue = randomNumberSupplier.get(); 
                          
                        

2. Consumer<T>:
  1. Abstract method: void accept(T t)
  2. This represents an operation that accepts a single input and returns no value or result.
  3. It is used for performing actions on input values, such as printing, saving, or processing.
                          
                            // Prints "Hello, World!"
                            Consumer<String> printMessage = message -> System.out.println(message);
                            printMessage.accept("Hello, World!"); 
                          
                        

3. Function<T, R>:
  1. Abstract method: R apply(T t)
  2. This represents a function that accepts one argument and produces a result.
  3. It is commonly used for mapping or transforming input to output.
                          
                            // "Number: 42"
                            Function<Integer, String> intToString = num -> "Number: " + num;
                            String result = intToString.apply(42); 
                          
                        

4. Predicate<T>:
  1. Abstract method: boolean test(T t)
  2. It represents a predicate/condition, a boolean-valued function that checks a condition on an input.
  3. It is used for filtering or testing elements based on a condition.
                          
                            // true
                            Predicate<Integer> isEven = num -> num % 2 == 0;
                            boolean result = isEven.test(8);