Interfaces Funcionais
Tags: beginners, java, java8
Published: 2020-08-31 13:39:00

---
title: Interfaces Funcionais
published: true
description: Esse post tem o objetivo de introduzir e discorrer um pouco sobre o conceito de interfaces funcionais.
tags: #beginner #java #java8
series: Revendo as funcionalidades do Java 8
---
As interfaces funcionais não surgiram no Java 8: nas versões mais antigas, já era possível encontrar esse tipo de interface. Mas foi no Java 8 que elas adquiriram maior importância, uma vez que elas são peças fundamentais para a implementação das expressões lambdas. Mas o que é uma interface funcional?

Uma interface funcional é uma interface que possui apenas um método abstrato. Ela pode ter mais de um método, mas se apenas um deles for abstrato, ela será considerada uma interface funcional. Vamos utilizar a interface Comparator para exemplificar:

```java
@FunctionalInterface
public interface Comparator<T> {
  int compare(T o1, T o2);
}
```
Essa interface contém mais métodos do que apenas o transcrito acima, e ela é interessante por alguns motivos que vou explicando ao longo do artigo. Para criar as comparações criei uma classe Livro:

```java
public class Livro{

    private String nome;
    private int qtdPaginas;

    public Livro(String nome, int qtdPaginas){
        this.nome = nome;
        this.qtdPaginas = qtdPaginas;
    }

    public String getNome() {
        return nome;
    }
    public void setNome(String nome) {
        this.nome = nome;
    }
    public int getQtdPaginas() {
        return qtdPaginas;
    }
    public void setQtdPaginas(int qtdPaginas) {
        this.qtdPaginas = qtdPaginas;
    }
}
```
A criação de um Comparator utilizando a classe Livro seria:

```java
 Comparator<Livro> comparator = new Comparator<Livro>() {
            @Override
            public int compare(Livro o1, Livro o2) {
                return o1.getNome().compareTo(o2.getNome());
            }
        };
```

Utilizando lambda, podemos ainda escrever o Comparator de forma mais simples:

```java
Comparator<Livro> porNome =
                (Livro o1, Livro o2)->o1.getNome().compareTo(o2.getNome());
```
Utilizando a classe anônima, vemos que o código fica um pouco confuso, porém o método que está sendo sobrescrito fica claro. Já quando utilizamos lambda, não fica explícito qual é o método da interface a ser sobrescrito, e é por isso que ela deve ser uma interface funcional: haverá apenas um método abstrato, que será sobrescrito.

Uma utilização desse 
Comparator:
```java
public static void main(String[] args){
        Comparator<Livro> porNome =
                (Livro o1, Livro o2)->o1.getNome().compareTo(o2.getNome());

        List<Livro> livros = new ArrayList<>();
        livros.add(new Livro("Morte e vida Severina", 240));
        livros.add(new Livro("Vidas Secas", 190));
        livros.add(new Livro("O Alienista", 150));
        livros.add(new Livro("Alice no País das Maravilhas", 300));

        livros.sort(porNome);
    }
```

Ou ainda de forma mais direta:
```java
public static void main(String[] args){
        List<Livro> livros = new ArrayList<>();
        livros.add(new Livro("Morte e vida Severina", 240));
        livros.add(new Livro("Vidas Secas", 190));
        livros.add(new Livro("O Alienista", 150));
        livros.add(new Livro("Alice no País das Maravilhas", 300));

        livros.sort((Livro o1, Livro o2)->o1.getNome().compareTo(o2.getNome()));
    }
```

Todos os métodos de interfaces no Java são por padrão públicos e abstratos. Porém, em uma interface funcional também podem ser encontrados _métodos default_. A interface Comparator possui diversos métodos default, como:

```java
@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);

    boolean equals(Object obj);

    default java.util.Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

    default <U> java.util.Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor,
            java.util.Comparator<? super U> keyComparator)
    {
        return thenComparing(comparing(keyExtractor, keyComparator));
    }
}

```
Como anteriormente dito, não transcrevi todos os métodos presentes na interface, apenas alguns para mostrar que a ela pode possuir mais métodos, desde que sejam _default methods_.

O método _boolean equals(Object obj);_ não descaracteriza a interface Comparator como funcional porque ele é uma sobrescrita do método _equals_ da classe Object.

Para evitar que uma interface funcional fosse descaracterizada acidentalmente causando prejuízo na utilização de expressões lambda, no Java 8 foi introduzida a anotação FunctionalInterface. É uma anotação opcional para manter as demais interfaces funcionais que já existiam antes da versão 8 do Java funcionando normalmente. Se não for colocada mas ainda assim a interface tiver apenas um método abstrato, ela será considerada funcional.

Outros exemplos de interfaces funcionais no Java:

Comparable:
```java
public interface Comparable<T> {
    public int compareTo(T o);
}
```

Runnable:
```java
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}
```
As interfaces Comparator e Runnable conceitualmente já eram consideradas interfaces funcionais antes de receberem a notação @FunctionalInterface no Java 8. A interface Comparable permanece sem a anotação.

Esse artigo faz parte de uma série que estou escrevendo enquanto revejo as funcionalidades do Java 8. Se gostou ou tem melhorias para sugerir, vou adorar saber!