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: ¿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.
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.