Functional Interface

Functional Interface

SAM Interface

Single Abstract Method Interfaces (SAM Interfaces) are also known as Functional Interfaces.A functional interface in Java is an interface that contains only one abstract method. They can have any number of default or static methods.

The main roles of functional interfaces are:

  • Support for Lambda Expressions and Method References
  • Support for Stream API

Here’s an example of a functional interface which is implemented using a lambda expression:

1
2
3
4
5
6
7
8
9
10
11
@FunctionalInterface
interface GreetingService {
void sayHello(String msg);
}

public class Main {
public static void main(String[] args) {
GreetingService greetService = (message) -> {System.out.println("Hello " + message)};
greetService.sayHello("Efterklang");
}
}

🪧Note:

  • The @FuncitonalInterface annotation is optional.
  • The parentheses () are optional if there is only one parameter.
  • The curly braces {} are optional if there is only one statement.

Create SAM Interface Instances

Instances of functional interfaces can be created with lambda expressions, method references, or constructor references.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@FunctionalInterface
interface Message {
void send(String name);
}

// λ Expressions
public class Main() {
public static void main(String[] args) {
Message message = (name) -> {
System.out.println("Sending email" + name);
};
message.send("Efterklang");
}
}

// Method References
/**
* In this example, System.out::println is a method reference that refers to the println method of the System.out object.
* The method reference is equivalent to the lambda expression x -> System.out.println(x).
* Here this reference acts as Consumer functional interface instance.
* void java.lang.Iterable.forEach(Consumer<? super String> action)
*/
public class Main() {
public static void main(String[] args) {
List<String> list = Arrays.asList("Apple", "Banana", "Cherry");
list.forEach(System.out::println);
}
}

// Constructor References
class Person {
private String name;

Person(String name) {
this.name = name;
}

String getName() {
return name;
}
}

@FunctionalInterface
interface PersonFactory {
Person create(String name);
}

PersonFactory factory = Person::new;
Person person = factory.create("John");
System.out.println(person.getName()); // Outputs: John

Examples of SAM Interfaces

Java’s standard library includes many commonly used SAM interfaces, such as Runnable, Callable, Comparable,Consumer, and many others in the java.util.function package.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@FunctionalInterface
public interface Runnable {
/**
* Runs this operation.
*/
void run();
}

@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}

@FunctionalInterface
public interface Comparable<T> {
public int compareTo(T o);
}

@FunctionalInterface
public interface Consumer<T> {

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

default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}

Here’s an example of using the Comparator and Consumer interfaces with lambda expressions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

class Student {
private String name;
private int age;

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
}

public class Main {
public static void main(String[] args) {
List<Student> students = Arrays.asList(
new Student("John", 20),
new Student("Alice", 22),
new Student("Bob", 18)
);
//Here comparator is a functional interface(Comparator<Student>) instance
Comparator<Student> comparator = Comparator.comparing(Student::getAge);
students.stream().sorted(comparator);
students.forEach(student -> {
System.out.println(student.getName()+ "," + student.getAge());
});
}
}
Author

Efterklang

Posted on

2024-02-10

Updated on

2024-09-18

Licensed under

Comments