Expressão lambda vs referência de método [fechado]

114

O IntelliJ continua me propondo a substituir minhas expressões lambda por referências de método.

Existe alguma diferença objetiva entre os dois?

Gerard
fonte
4
Na verdade não, não vejo nenhum objeto! Parece uma chamada estática para mim
Gerard
9
Claro! Mas também "não achas" ... É uma questão de gosto, estava mais preocupado com os aspectos mais técnicos. Na verdade, como você já disse que eles são iguais, essa é uma boa resposta para mim. De qualquer forma, como o IntelliJ propõe, acho que geralmente é mais apreciado ver uma referência de método do que um lambda (embora não para mim).
Gerard
15
O código de uma expressão lambda é compilado para um método sintético, enquanto as referências de método funcionam sem (exceção: construções especiais como Type[]::new). A classe anônima gerada em tempo de execução será a mesma. O JRE não faz diferença entre eles. Portanto, usar uma referência de método irá economizar um método em seu código compilado, por outro lado, você não pode parar neles ao fazer a depuração passo a passo ...
Holger
6
Agora a questão vai ser encerrada ... Pena para todos os usuários como eu que não sabem a diferença entre lambdas e referências, mesmo que não haja nenhuma decisiva. Também me pergunto por que ninguém se atreveu a responder isso? Essa é a resposta certa para mim.
Gerard
3
Responder a uma pergunta fechada de dois anos é provavelmente uma má ideia, mas para aqueles que LERAM REALMENTE a pergunta, este é o que o tutorial do Oracle ( docs.oracle.com/javase/tutorial/java/javaOO/… ) diz: Referências de método ... são expressões lambda compactas e fáceis de ler para métodos que já têm um nome.
amanhã

Respostas:

187

Deixe-me oferecer uma perspectiva sobre por que adicionamos esse recurso à linguagem, quando claramente não é necessário (todos os métodos refs podem ser expressos como lambdas.)

Observe que não existe uma resposta certa . Qualquer pessoa que diga "sempre use um método ref em vez de um lambda" ou "sempre use um lambda em vez de um método ref" deve ser ignorado.

Esta pergunta é muito semelhante em espírito a "quando devo usar uma classe nomeada em vez de uma classe anônima"? E a resposta é a mesma: quando você achar mais legível . Certamente há casos que são definitivamente um ou definitivamente o outro, mas há uma porção de cinza no meio, e o julgamento deve ser usado.

A teoria por trás do método refs é simples: os nomes são importantes . Se um método tem um nome, então referir-se a ele pelo nome, em vez de por um pacote imperativo de código que no final das contas apenas o invoca e se volta, é frequentemente (mas nem sempre!) Mais claro e legível.

Os argumentos sobre desempenho ou contagem de caracteres são, em sua maioria, pistas falsas e você deve ignorá-los. O objetivo é escrever um código que seja absolutamente claro o que ele faz. Muitas vezes (mas nem sempre!) O método refs vence nessa métrica, então nós os incluímos como uma opção, para serem usados ​​nesses casos.

Uma consideração importante sobre se o método refs esclarece ou ofusca a intenção é se é óbvio a partir do contexto qual é a forma da função que está sendo representada. Em alguns casos (por exemplo, map(Person::getLastName)é bastante claro a partir do contexto que uma função que mapeia uma coisa para outra é necessária, e em casos como este, as referências de método brilham. Em outros, usar um método ref exige que o leitor se pergunte sobre qual tipo da função está sendo descrita; este é um sinal de aviso de que um lambda pode ser mais legível, mesmo se for mais longo.

Finalmente, o que descobrimos é que a maioria das pessoas no início se afasta dos métodos refs porque eles se sentem ainda mais novos e mais estranhos do que lambdas, e assim inicialmente os acham "menos legíveis", mas com o tempo, quando se acostumam com a sintaxe, geralmente mudam seu comportamento e gravitam em torno de referências de métodos quando podem. Portanto, esteja ciente de que sua própria reação subjetiva inicial "menos legível" quase certamente envolve algum aspecto de viés familiar, e você deve se dar a chance de se sentir confortável com ambos antes de apresentar uma opinião estilística.

Brian Goetz
fonte
25
@Gerard Obrigado teria sido uma resposta melhor.
Yassin Hajaj
3
@Gerard Parece que Brian está dizendo "Não, não há"
dj18
Brian, obtenho resultados diferentes usando uma referência de método e um lambda para o mesmo método. Eles não deveriam ser intercambiáveis?
Michel Feinstein
@mFeinstein Para cada método ref, há um lambda equivalente (que você pode ou não usar). Postar o código como uma pergunta?
Brian Goetz
Eu quero, mas temo que o código possa ser muito grande, já que é um Android LiveData, dentro de um Fragment, que converti em um Eventque é acionado por um ViewModel... e o comportamento diferente acontece quando o Android volta para o mesmo Fragment.. .então estou tendo dificuldade em simplificar para uma pergunta
Michel Feinstein
10

Expressões lambda longas que consistem em várias instruções podem reduzir a legibilidade de seu código. Nesse caso, extrair essas instruções em um método e fazer referência a ele pode ser uma escolha melhor.

O outro motivo pode ser a reutilização . Em vez de copiar e colar sua expressão lambda de algumas instruções, você pode construir um método e chamá-lo de diferentes locais do código.

ovunccetina
fonte
3
Compare: houses.map(House::getName)e houses.map(h -> h.getName()). O lambda leva menos dois caracteres. É verdade que o tipo não é explícito, mas qualquer IDE diria a você e, além disso, lambdas devem ser usados ​​quando o tipo é óbvio. Posso concordar com você sobre a reutilização, mas lambdas são precisamente pequenos, então podem ser encadeados em vez de criar grandes métodos específicos. Nesse sentido, métodos pequenos são mais reutilizáveis ​​do que alguns métodos grandes e complexos e, devido à clareza dos lambdas (e até certo ponto, verbosidade), ainda são fáceis de ler.
Gerard
11
Estou com Gerald. A legibilidade na verdade é prejudicada quando você remove o código, então você tem que pular para continuar lendo e depois voltar. Você deseja ter todos os códigos relevantes no mesmo lugar. Além disso, Houseé um exemplo muito benigno; sobre o que ThreeStoryRedBrickHouseWithBlueDoors. Eu prefiro referências de método para lambdas de vários argumentos e, às vezes, para enfatizar que lambda é apenas sobre uma única chamada de método. Há menos coisas para dar errado com uma referência de método: você pode digitar incorretamente o argumento em use site, acidentalmente se referindo a uma variável do escopo externo, etc.
Marko Topolnik
@Gerard Não concordo com sua primeira declaração. Se você usar nomes de métodos bem descritivos e extrair grandes pilhas de código, mover o código melhora a legibilidade. Se você usar nomes de métodos ofuscantes, concordo com você.
Torsten