Interfaces Funcionais e Lambdas
Interfaces funcionais (SAM Types - Single Abstract Method) são essenciais para expressões lambda. O lambda só existe quando associado a uma interface funcional. Sem essa associação, o código não compila.
Exemplo de Erro:
Object o = () -> {
System.out.println("O que sou eu? Que lambda?");
};
// Erro: Object não é uma interface funcional!
Exemplo Correto com Runnable:
Runnable o = () -> {
System.out.println("O que sou eu? Que lambda?");
};
Como os Lambdas São Implementados
O compilador gera classes dinamicamente para representar lambdas, usando MethodHandles e invokedynamic. Essas classes não são visíveis como arquivos .class, mas podem ser identificadas em tempo de execução:
Runnable o = () -> {
System.out.println("Classe gerada dinamicamente!");
};
System.out.println(o.getClass());
// Saída: Capitulo3$$Lambda$1@1fc625e
O nome da classe gerada (ex: Capitulo3$$Lambda$1) depende do contexto e do número de lambdas na classe.
Captura de Variáveis Locais
Lambdas podem acessar variáveis locais do método em que estão definidos, mas elas devem ser efetivamente finais (não modificadas após serem usadas no lambda).
Exemplo 1: Variável Final Explícita
public static void main(String[] args) {
final int numero = 5;
new Thread(() -> {
System.out.println(numero); // Funciona: variável final
}).start();
}
Exemplo 2: Variável Efetivamente Final (não declarada como final)
public static void main(String[] args) {
int numero = 5;
new Thread(() -> {
System.out.println(numero); // Funciona: não é modificada
}).start();
}
Exemplo 3: Erro ao Modificar a Variável
public static void main(String[] args) {
int numero = 5;
new Thread(() -> {
System.out.println(numero); // Não compila!
}).start();
numero = 10; // Variável alterada após ser usada no lambda
}
Observações Importantes:
Regra da Variável Efetivamente Final:
A partir do Java 8, variáveis locais usadas em lambdas (ou classes anônimas) não precisam ser declaradas como final, mas não podem ser modificadas após serem capturadas.
Concorrência e Estado:
Acesso a objetos mutáveis dentro de lambdas pode causar problemas de concorrência (abordado em capítulos posteriores).
Conclusão:
- Lambdas dependem de interfaces funcionais para existir.
- Classes dinâmicas são geradas em tempo de execução para implementar lambdas.
- Variáveis capturadas devem ser imutáveis (efetivamente finais).
Essas regras garantem segurança e consistência no uso de lambdas, mantendo a legibilidade e a concisão do código.
Top comments (0)