0Pricing
Java Academy · Lección

Interfaces funcionales personalizadas

Defina la suya con @FunctionalInterface

Interfaces funcionales personalizadas es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.

Qué hace que una interfaz sea funcional

Una interfaz funcional tiene exactamente un método abstracto (SAM). Ese único método es el que implementa una lambda.

  • Los métodos predeterminados y estáticos no cuentan para el límite.
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"));
    }
}

La anotación @FunctionalInterface

@FunctionalInterface indica al compilador que debe hacer cumplir la regla del método único abstracto. Si añade accidentalmente un segundo método abstracto, la compilación falla.

@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 qué resulta útil la anotación

La anotación documenta la intención y protege el contrato. Sin ella, la interfaz sigue funcionando como funcional, pero otro miembro del equipo podría romperla al añadir otro método abstracto.

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

Interfaz personalizada con genéricos

Su interfaz puede ser genérica, igual que las 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);
    }
}

Se permiten métodos predeterminados

Una interfaz funcional puede tener métodos default. Estos añaden comportamiento sin romper la regla del método único abstracto.

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

También se permiten métodos estáticos

Los métodos estáticos pueden actuar como fábricas, de forma similar 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));
    }
}

Lanzamiento de excepciones comprobadas

Si su método abstracto declara una excepción comprobada, la lambda puede lanzarla. La Function integrada no puede hacerlo, lo que constituye una de las razones para definir una interfaz propia.

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

Pasar interfaces personalizadas a métodos

Su interfaz se convierte en un tipo de parámetro, lo que permite que los llamadores proporcionen comportamiento mediante lambdas.

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

Interfaz de tres argumentos

El JDK solo incluye interfaces de uno y dos argumentos. Para tres o más argumentos, defina una interfaz propia.

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

Las referencias a métodos se adaptan a interfaces personalizadas

Cualquier método cuya signatura coincida con el SAM puede proporcionarse como referencia a un 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("   "));
    }
}

Clase anónima frente a lambda

Una lambda es una alternativa concisa a una clase anónima que implementa una interfaz funcional. Ambas producen el mismo comportamiento.

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

Comprobación rápida

¿Qué garantiza @FunctionalInterface?

Resumen

Definió sus propias interfaces funcionales:

  • Una interfaz funcional tiene exactamente un método abstracto (SAM).
  • @FunctionalInterface hace cumplir esa regla en tiempo de compilación.
  • Se permiten métodos predeterminados y estáticos, genéricos y excepciones comprobadas.
  • Las interfaces personalizadas cubren carencias que el JDK no contempla, como funciones de tres argumentos o lambdas que lanzan excepciones comprobadas.

Preguntas frecuentes

¿La lección «Interfaces funcionales personalizadas» es gratis?

Sí — el texto completo de «Interfaces funcionales personalizadas» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Interfaces funcionales personalizadas»?

Defina la suya con @FunctionalInterface Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Java Academy?

No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Interfaces funcionales personalizadas»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Java Academy?

Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Function y BiFunction
  2. Supplier y Consumer
  3. Predicate y composición
  4. Interfaces funcionales personalizadas
← Volver a Java Academy