ProgramaciónDesarrollador Java

Explique cómo funcionan las expresiones lambda y las interfaces funcionales en Java. ¿Qué errores pueden surgir de su uso incorrecto?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

Las expresiones lambda se introdujeron en Java 8 para un estilo de sintaxis más conciso al implementar interfaces con un solo método (interfaces funcionales).

Una interfaz funcional es una interfaz con exactamente un método abstracto. Ejemplo:

@FunctionalInterface interface MyAction { void perform(String s); }

Una expresión lambda permite implementar dicha interfaz:

MyAction action = (s) -> System.out.println(s); action.perform("¡Hola lambda!");

Al usar una expresión lambda, el compilador entiende por sí mismo qué interfaz se está implementando (tipado de objetivo). Las lambdas se utilizan a menudo con colecciones:

List<String> list = Arrays.asList("uno", "dos", "tres"); list.forEach(s -> System.out.println(s));

Pregunta capciosa

Pregunta: ¿Puede una expresión lambda referirse a campos o métodos no estáticos de una clase externa? ¿Qué limitaciones existen al respecto?

Respuesta: Una expresión lambda puede referirse a campos y métodos de la clase externa, pero si utiliza variables locales del método externo, estas variables deben ser final o effectively final (es decir, no deben cambiarse después de la primera asignación). Por ejemplo:

void doIt() { int x = 42; Runnable r = () -> System.out.println(x); // x debe ser effectively final }

Si se cambia x después de la declaración, ocurrirá un error de compilación.

Ejemplos de errores reales debido al desconocimiento de los matices del tema


Historia

Al usar una lambda dentro de un método, se intentó modificar una variable local externa, lo que provocó un error de compilación "La variable utilizada en la expresión lambda debe ser final o effectively final". Los desarrolladores pasaron mucho tiempo buscando la causa, hasta que recordaron esta limitación.


Historia

En un proyecto se usaron interfaces propias para las lambdas, pero olvidaron anotarlas con @FunctionalInterface. Después de una refactorización, se agregó un segundo método a la interfaz y el proyecto dejó de compilar. Esto causó errores inesperados que fueron difíciles de detectar.


Historia

Un intento de serializar un objeto que contenía un campo con una expresión lambda provocó que la serialización/deserialización no funcionara correctamente: la lambda no se serializa por defecto. Es importante recordar que si una lambda contiene dependencias inconsistentes, se producirán errores al ser transmitida por la red.