DEV Community

FUNDAMENTOS JAVA
FUNDAMENTOS JAVA

Posted on

3.4 Indo mais afundo: primeiros detalhes

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!  
Enter fullscreen mode Exit fullscreen mode

Exemplo Correto com Runnable:

Runnable o = () -> {  
    System.out.println("O que sou eu? Que lambda?");  
};  
Enter fullscreen mode Exit fullscreen mode

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  
Enter fullscreen mode Exit fullscreen mode

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();  
}  
Enter fullscreen mode Exit fullscreen mode

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();  
}  
Enter fullscreen mode Exit fullscreen mode

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  
}  

Enter fullscreen mode Exit fullscreen mode

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)