Como o Java8 foi lançado recentemente e suas novas expressões lambda parecem ser muito legais, eu queria saber se isso significa o fim das classes Anonymous com as quais estávamos tão acostumados.
Estive pesquisando um pouco sobre isso e encontrei alguns exemplos interessantes de como as expressões Lambda substituirão sistematicamente essas classes, como o método de classificação da Coleção, que costumava obter uma instância Anônima de Comparator para realizar a classificação:
Collections.sort(personList, new Comparator<Person>(){
public int compare(Person p1, Person p2){
return p1.firstName.compareTo(p2.firstName);
}
});
Agora pode ser feito usando Lambdas:
Collections.sort(personList, (Person p1, Person p2) -> p1.firstName.compareTo(p2.firstName));
E parece surpreendentemente conciso. Portanto, minha pergunta é: há algum motivo para continuar usando essas classes em Java8 em vez de Lambdas?
EDITAR
Mesma pergunta, mas na direção oposta, quais são os benefícios de usar Lambdas em vez de classes anônimas, uma vez que Lambdas só podem ser usados com interfaces de método único, esse novo recurso é apenas um atalho usado em poucos casos ou é realmente útil?
fonte
Comparator.comparing(Person::getFirstName)
segetFirstName()
seria um método que retornafirstName
.Respostas:
Uma classe interna anônima (AIC) pode ser usada para criar uma subclasse de uma classe abstrata ou uma classe concreta. Um AIC também pode fornecer uma implementação concreta de uma interface, incluindo a adição de estado (campos). Uma instância de um AIC pode ser referenciada usando
this
em seus corpos de método, portanto, métodos adicionais podem ser chamados, seu estado pode ser mutado com o tempo, etc. Nenhum desses se aplica a lambdas.Eu acho que a maioria dos usos de AICs era para fornecer implementações sem estado de funções únicas e, portanto, podem ser substituídos por expressões lambda, mas existem outros usos de AICs para os quais lambdas não podem ser usados. Os AICs estão aqui para ficar.
ATUALIZAR
Outra diferença entre AICs e expressões lambda é que os AICs introduzem um novo escopo. Ou seja, os nomes são resolvidos a partir das superclasses e interfaces do AIC e podem sombrear nomes que ocorrem no ambiente envolvente lexicamente. Para lambdas, todos os nomes são resolvidos lexicamente.
fonte
A$1.class
mas o Lambda não. Posso adicionar isso na diferença?LambdaClass$$Lambda$1/1078694789
. No entanto, essa classe é gerada instantaneamente pela metafábrica lambda, não pelajavac
, portanto, não há.class
arquivo correspondente . Novamente, no entanto, essa é uma preocupação de implementação.Lambdas embora seja um ótimo recurso, só funcionará com tipos de SAM. Ou seja, interfaces com apenas um único método abstrato. Ele falhará assim que sua interface contiver mais de 1 método abstrato. É aí que as classes anônimas serão úteis.
Então, não, não podemos simplesmente ignorar classes anônimas. E apenas para sua informação, seu
sort()
método pode ser mais simplificado, pulando a declaração de tipo parap1
ep2
:Você também pode usar a referência de método aqui. Você adiciona um
compareByFirstName()
método naPerson
classe e usa:ou adicione um getter para
firstName
obter diretamente o métodoComparator
fromComparator.comparing()
:fonte
new @MyTypeAnnotation SomeInterface(){};
. Isso não é possível para expressões lambda. Para obter detalhes, veja minha pergunta aqui: Anotando a interface funcional de uma Expressão Lambda .Desempenho lambda com classes anônimas
Quando o aplicativo é iniciado, cada arquivo de classe deve ser carregado e verificado.
As classes anônimas são processadas pelo compilador como um novo subtipo para a classe ou interface fornecida, portanto, será gerado um novo arquivo de classe para cada uma.
Lambdas são diferentes na geração de bytecode, são mais eficientes, usam a instrução invokedynamic que vem com o JDK7.
Para Lambdas, esta instrução é usada para atrasar a tradução da expressão lambda em bytecode até o tempo de execução. (a instrução será invocada apenas pela primeira vez)
Como resultado, a expressão Lambda se tornará um método estático (criado em tempo de execução). (Há uma pequena diferença com stateles e casos com estado, eles são resolvidos por meio de argumentos de método gerados)
fonte
invokedynamic
qual geralmente é mais lento do que oinvokespecial
usado para criar novas instâncias de classes anônimas. Portanto, nesse sentido, os lambdas também são mais lentos (no entanto, a JVM pode otimizar asinvokedynamic
chamadas na maioria das vezes).invokedynamic
com classes ad-hoc, a geração é extremamente rápida em comparação com classes anônimas compiladas.Existem as seguintes diferenças:
1) Sintaxe
Expressões lambda parecem legais em comparação com Anonymous Inner Class (AIC)
2. Âmbito
Uma classe interna anônima é uma classe, o que significa que ela tem escopo para variáveis definidas dentro da classe interna.
Enquanto que a expressão lambda não é um escopo próprio, mas faz parte do escopo envolvente.
Uma regra semelhante se aplica a super e esta palavra - chave ao usar dentro da classe interna anônima e expressão lambda. No caso de classe interna anônima, esta palavra-chave se refere ao escopo local e a palavra-chave super se refere à superclasse da classe anônima. Enquanto no caso da expressão lambda, esta palavra-chave se refere ao objeto do tipo envolvente e super se refere à superclasse da classe envolvente.
3) Desempenho
Em tempo de execução, as classes internas anônimas exigem carregamento de classe, alocação de memória e inicialização de objeto e invocação de um método não estático, enquanto a expressão lambda é pura atividade de tempo de compilação e não incorre em custos extras durante o tempo de execução. Portanto, o desempenho da expressão lambda é melhor em comparação com as classes internas anônimas. **
** Sei que este ponto não é totalmente verdadeiro. Consulte a pergunta a seguir para obter detalhes. Lambda vs desempenho de classe interna anônima: reduzindo a carga no ClassLoader?
fonte
Lambda's em java 8 foi introduzido para programação funcional. Onde você pode evitar o código clichê. Me deparei com um artigo interessante sobre lambda.
http://radar.oreilly.com/2014/04/whats-new-in-java-8-lambdas.html
É aconselhável usar funções lambda para lógicas simples. Se implementar lógica complexa usando lambdas, será uma sobrecarga na depuração do código em caso de problema.
fonte
As classes anônimas estão aí para ficar porque lambda é bom para funções com métodos abstratos únicos, mas para todos os outros casos as classes internas anônimas são o seu salvador.
fonte
invoke dynamic
, lambda não é convertido de volta para as classes anônimas durante o tempo de compilação (Java não precisa passar pela criação de objetos, apenas se preocupa com a assinatura do método, pode vincular ao método sem criar objetofonte