﻿---
title: Functional Interface
date: 2024-02-10
excerpt: Single Abstract Method Interfaces (SAM Interfaces) are also known as Functional Interfaces. This article explains how to create and use SAM interfaces in Java.
tags:
  - Java
cover: https://assets.vluv.space/cover/Dev/Java/Func_Interface.webp
---

## 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:

```java
@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.

```java
@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.

```java
@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:

```java
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());
        });
    }
}
```
