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());
});
}
}
Functional Interface