Em muitas cenas, acho que lambda e method-reference são equivalentes. Mas o lambda irá envolver o alvo de invocação pelo tipo de interface declarante.
Por exemplo
public class InvokeTest {
private static void invoke(final Runnable r) {
r.run();
}
private static void target() {
new Exception().printStackTrace();
}
@Test
public void lambda() throws Exception {
invoke(() -> target());
}
@Test
public void methodReference() throws Exception {
invoke(InvokeTest::target);
}
}
Você verá o console gerando o stacktrace.
Em lambda()
, o método que chama target()
é lambda$lambda$0(InvokeTest.java:20)
, que contém informações de linha rastreáveis. Obviamente, esse é o lambda que você escreve, o compilador gera um método anônimo para você. E então, o chamador do método lambda é algo como InvokeTest$$Lambda$2/1617791695.run(Unknown Source)
, que é a chamada invokedynamic
na JVM, isso significa que a chamada está vinculada ao método gerado .
Em methodReference()
, o método que chama target()
é diretamente o InvokeTest$$Lambda$1/758529971.run(Unknown Source)
, isso significa que a ligação está vinculada diretamente ao método InvokeTest::target
.