0Pricing
Java Academy · Aula

Interfaces funcionais personalizadas

Defina a sua própria com @FunctionalInterface.

Interfaces funcionais personalizadas é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.

O que torna uma interface funcional

Uma interface funcional tem exatamente um método abstrato (SAM). Esse único método é o que uma expressão lambda implementa.

  • Métodos padrão e estáticos não contam para o limite.
interface Greeter {
    String greet(String name);
}

public class Main {
    public static void main(String[] args) {
        Greeter g = name -> "Hello, " + name;
        System.out.println(g.greet("Ada"));
    }
}

A anotação @FunctionalInterface

@FunctionalInterface instrui o compilador a impor a regra de um único método abstrato. Se você adicionar acidentalmente um segundo método abstrato, a compilação falhará.

@FunctionalInterface
interface Calculator {
    int compute(int a, int b);
}

public class Main {
    public static void main(String[] args) {
        Calculator add = (a, b) -> a + b;
        System.out.println(add.compute(3, 4));
    }
}

Por que a anotação ajuda

A anotação documenta a intenção e protege o contrato. Sem ela, a interface ainda funciona como funcional, mas alguém da equipe poderia quebrá-la adicionando outro método abstrato.

@FunctionalInterface
interface Transformer {
    String apply(String input);
}

public class Main {
    public static void main(String[] args) {
        Transformer reverse = s -> new StringBuilder(s).reverse().toString();
        System.out.println(reverse.apply("abc"));
    }
}

Interface personalizada com genéricos

Sua interface pode ser genérica, assim como as interfaces integradas.

@FunctionalInterface
interface Converter<S, T> {
    T convert(S source);
}

public class Main {
    public static void main(String[] args) {
        Converter<String, Integer> toInt = Integer::parseInt;
        System.out.println(toInt.convert("123") + 1);
    }
}

Métodos default são permitidos

Uma interface funcional pode ter métodos default. Eles adicionam comportamento sem quebrar a regra de um único método abstrato.

@FunctionalInterface
interface Operation {
    int apply(int x);

    default Operation then(Operation next) {
        return x -> next.apply(this.apply(x));
    }
}

public class Main {
    public static void main(String[] args) {
        Operation inc = x -> x + 1;
        Operation dbl = x -> x * 2;
        System.out.println(inc.then(dbl).apply(5));
    }
}

Métodos estáticos também são permitidos

Métodos estáticos podem funcionar como fábricas, de modo semelhante a Function.identity().

@FunctionalInterface
interface Mapper {
    int map(int x);

    static Mapper identity() {
        return x -> x;
    }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(Mapper.identity().map(99));
    }
}

Lançamento de exceções verificadas

Se o seu método abstrato declarar uma exceção verificada, a expressão lambda poderá lançá-la. A Function integrada não pode fazer isso, o que é uma das razões para definir a sua própria.

@FunctionalInterface
interface RiskyParser {
    int parse(String s) throws NumberFormatException;
}

public class Main {
    public static void main(String[] args) {
        RiskyParser p = Integer::parseInt;
        System.out.println(p.parse("77"));
    }
}

Passagem de interfaces personalizadas para métodos

Sua interface se torna um tipo de parâmetro, permitindo que quem chama forneça comportamento por meio de expressões lambda.

@FunctionalInterface
interface IntCombiner {
    int combine(int a, int b);
}

public class Main {
    static int reduce(int[] arr, IntCombiner c) {
        int acc = arr[0];
        for (int i = 1; i < arr.length; i++) acc = c.combine(acc, arr[i]);
        return acc;
    }

    public static void main(String[] args) {
        int[] data = {1, 2, 3, 4};
        System.out.println(reduce(data, (a, b) -> a + b));
    }
}

Interface para três argumentos

O JDK fornece apenas interfaces para um e dois argumentos. Para três ou mais argumentos, defina a sua própria.

@FunctionalInterface
interface TriFunction<A, B, C, R> {
    R apply(A a, B b, C c);
}

public class Main {
    public static void main(String[] args) {
        TriFunction<Integer, Integer, Integer, Integer> sum3 = (a, b, c) -> a + b + c;
        System.out.println(sum3.apply(1, 2, 3));
    }
}

Referências a métodos são compatíveis com interfaces personalizadas

Qualquer método cuja assinatura corresponda ao SAM pode ser fornecido como uma referência a método.

@FunctionalInterface
interface StringTest {
    boolean check(String s);
}

public class Main {
    public static void main(String[] args) {
        StringTest blank = String::isBlank;
        System.out.println(blank.check("   "));
    }
}

Classe anônima versus expressão lambda

Uma expressão lambda é uma substituição concisa para uma classe anônima que implementa uma interface funcional. Ambas produzem o mesmo comportamento.

@FunctionalInterface
interface Action {
    void run();
}

public class Main {
    public static void main(String[] args) {
        Action old = new Action() {
            public void run() { System.out.println("anonymous"); }
        };
        Action neo = () -> System.out.println("lambda");
        old.run();
        neo.run();
    }
}

Verificação rápida

O que @FunctionalInterface garante?

Recapitulação

Você definiu suas próprias interfaces funcionais:

  • Uma interface funcional tem exatamente um método abstrato (SAM).
  • @FunctionalInterface impõe essa regra no momento da compilação.
  • Métodos default e estáticos, genéricos e exceções verificadas são permitidos.
  • Interfaces personalizadas preenchem lacunas que o JDK não cobre, como funções com três argumentos ou expressões lambda que lançam exceções verificadas.

Perguntas Frequentes

A aula “Interfaces funcionais personalizadas” é grátis?

Sim — o texto completo de “Interfaces funcionais personalizadas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.

O que vou aprender em “Interfaces funcionais personalizadas”?

Defina a sua própria com @FunctionalInterface. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Java Academy?

Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Interfaces funcionais personalizadas”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Java Academy?

Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Function e BiFunction
  2. Supplier e Consumer
  3. Predicate e composição
  4. Interfaces funcionais personalizadas
← Voltar para Java Academy