Qual é o tipo de uma expressão Lambda?
1 Lambda precisa ter um tipo funcional Lambdas não podem ser atribuídas a tipos que não são interfaces funcionais, como Object. Exemplo que não compila: Object o = () -> { System.out.println("eu sou um runnable!"); }; new Thread(o).start(); // Erro 2 Lambda atribuída corretamente a uma interface funcional Atribuindo explicitamente para Runnable: Runnable r = () -> { System.out.println("eu sou um runnable!"); }; new Thread(r).start(); // Correto 3 Lambda passada diretamente como argumento Quando passamos diretamente no construtor, o compilador usa o contexto para inferir o tipo: new Thread(() -> { System.out.println("eu sou um runnable?"); }).start(); O construtor Thread(Runnable r) espera um Runnable, então o compilador infere que a lambda é Runnable. 4 Target Type O tipo esperado pelo compilador baseado no contexto é chamado de Target Type. O Target Type permite: Inferir o tipo da expressão lambda; Reconhecer que uma mesma lambda pode representar diferentes interfaces funcionais. Exemplo com mesma expressão lambda e diferentes tipos: Callable c = () -> "retorna uma String"; PrivilegedAction p = () -> "retorna uma String"; Na primeira linha: Callable. Na segunda linha: PrivilegedAction. O Target Type define o significado. 5 O mesmo acontece com Method Reference A method reference também usa Target Type para inferência. Exemplo com method reference Callable c = callable::call; PrivilegedAction action = callable::call; A mesma referência callable::call pode se adaptar a diferentes interfaces. 6 Diferença entre Lambda e Method Reference Method references tornam a inferência mais forte, porque o tipo está mais explícito. Além disso, é permitida a conversão entre interfaces funcionais compatíveis. Exemplo: ExemploTargetType.java

1 Lambda precisa ter um tipo funcional
Lambdas não podem ser atribuídas a tipos que não são interfaces funcionais, como Object.
Exemplo que não compila:
Object o = () -> {
System.out.println("eu sou um runnable!");
};
new Thread(o).start(); // Erro
2 Lambda atribuída corretamente a uma interface funcional
Atribuindo explicitamente para Runnable:
Runnable r = () -> {
System.out.println("eu sou um runnable!");
};
new Thread(r).start(); // Correto
3 Lambda passada diretamente como argumento
Quando passamos diretamente no construtor, o compilador usa o contexto para inferir o tipo:
new Thread(() -> {
System.out.println("eu sou um runnable?");
}).start();
O construtor Thread(Runnable r) espera um Runnable, então o compilador infere que a lambda é Runnable.
4 Target Type
O tipo esperado pelo compilador baseado no contexto é chamado de Target Type.
O Target Type permite:
Inferir o tipo da expressão lambda;
Reconhecer que uma mesma lambda pode representar diferentes interfaces funcionais.
Exemplo com mesma expressão lambda e diferentes tipos:
Callable
PrivilegedAction
Na primeira linha: Callable.
Na segunda linha: PrivilegedAction.
O Target Type define o significado.
5 O mesmo acontece com Method Reference
A method reference também usa Target Type para inferência.
Exemplo com method reference
Callable
PrivilegedAction
A mesma referência callable::call pode se adaptar a diferentes interfaces.
6 Diferença entre Lambda e Method Reference
Method references tornam a inferência mais forte, porque o tipo está mais explícito.
Além disso, é permitida a conversão entre interfaces funcionais compatíveis.
Exemplo: ExemploTargetType.java