0Pricing
Java Academy · Lezione

Interfacce funzionali personalizzate

Definirne una con @FunctionalInterface

Interfacce funzionali personalizzate è una lezione Java Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Java Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Java Academy include 4 lezioni in totale.

Quando un'interfaccia è funzionale

Un'interfaccia funzionale ha esattamente un metodo astratto (SAM). È questo unico metodo che viene implementato da una lambda.

  • I metodi default e statici non vengono conteggiati nel 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"));
    }
}

L'annotazione @FunctionalInterface

@FunctionalInterface indica al compilatore di applicare la regola del singolo metodo astratto. Se aggiunge accidentalmente un secondo metodo astratto, la compilazione fallisce.

@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));
    }
}

Perché l'annotazione è utile

L'annotazione documenta l'intento e protegge il contratto. Senza di essa, l'interfaccia continua a funzionare come interfaccia funzionale, ma un collega potrebbe comprometterla aggiungendo un altro metodo astratto.

@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"));
    }
}

Interfaccia personalizzata con generics

La sua interfaccia può essere generica, proprio come quelle integrate.

@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);
    }
}

I metodi default sono consentiti

Un'interfaccia funzionale può avere metodi default. Questi aggiungono comportamento senza violare la regola del singolo metodo astratto.

@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));
    }
}

Anche i metodi statici sono consentiti

I metodi statici possono fungere da factory, in modo simile 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));
    }
}

Lanciare eccezioni checked

Se il metodo astratto dichiara un'eccezione checked, la lambda può lanciarla. La Function integrata non può farlo: è uno dei motivi per cui può essere utile definirne una personalizzata.

@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"));
    }
}

Passare interfacce personalizzate ai metodi

La sua interfaccia diventa un tipo di parametro, consentendo ai chiamanti di fornire il comportamento tramite 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));
    }
}

Interfaccia con tre argomenti

Il JDK fornisce interfacce con uno o due argomenti. Per tre o più argomenti, ne definisca una personalizzata.

@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));
    }
}

I riferimenti a metodi si adattano alle interfacce personalizzate

Qualsiasi metodo la cui firma corrisponde al SAM può essere fornito come riferimento a un metodo.

@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 anonima e lambda

Una lambda è una sostituzione concisa di una classe anonima che implementa un'interfaccia funzionale. Entrambe producono lo stesso 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 rapida

Che cosa garantisce @FunctionalInterface?

Riepilogo

Ha definito le sue interfacce funzionali:

  • Un'interfaccia funzionale ha esattamente un metodo astratto (SAM).
  • @FunctionalInterface applica questa regola in fase di compilazione.
  • I metodi default e statici, i generics e le eccezioni checked sono tutti consentiti.
  • Le interfacce personalizzate colmano le lacune non coperte dal JDK, come le funzioni con tre argomenti o le lambda che lanciano eccezioni checked.

Domande Frequenti

La lezione «Interfacce funzionali personalizzate» è gratuita?

Sì — il testo completo di «Interfacce funzionali personalizzate» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Java Academy, passa a CoddyKit PRO. Il corso Java Academy include 4 lezioni in totale.

Cosa imparerò in «Interfacce funzionali personalizzate»?

Definirne una con @FunctionalInterface Eserciti Java Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Java Academy?

Non è richiesta alcuna esperienza precedente. Java Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.

Quanto tempo richiede la lezione «Interfacce funzionali personalizzate»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Java Academy?

Sì. Ogni lezione Java Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Function e BiFunction
  2. Supplier e Consumer
  3. Predicate e composizione
  4. Interfacce funzionali personalizzate
← Torna a Java Academy