Trabalhando com closures no Java 8

Postado em 11. jan, 2011 por Paulo Silveira em Java

java logoCriar em Java um simples Runnable ou ActionListener pode ocupar muitas linhas de código. A solução preferida dos programadores hoje é usar as classes anônimas do Java:

Runnable r = new Runnable() {
  public void run() {
    System.out.println("Caelum"); 
  }
};
new Thread(r).start();

Depois de muitas propostas para closures no Java, a proposta atual de Lambdas para o Java 8 permite omitir a declaração do método, no caso de haver apenas um método abstrato naquela classe abstrata/interface (single abstract method):

Runnable r = #{System.out.println("Caelum")};
new Thread(r).start();

Mais ainda: o compilador consegue inferir um passo adiante, descobrindo que há um construtor em Thread que recebe como argumento uma interface que possui apenas um método abstrato. Repare que agora não precisamos escrever nem Runnable, nem run:

new Thread(#{System.out.println("Caelum")}).start();

Esses recursos, somados aos polêmicos defender methods (que permitem indicar “defaults” para métodos em interfaces), permitirão escrever lista.sortBy(#Usuario.getNome), muito mais sucinto do que invocar Collections.sort(lista, ...) passando um new Comparator() {...} que invoca u1.getNome.compareTo().

Como rodar esses testes? O Java 7 está previsto já para junho, mas infelizmente não contemplará muitos dos esperados avanços na linguagem. Esses ficarão para meados de 2012, com o Java 8, mas você já pode experimentá-los. Para isso, precisa ter o Java 7 instalado (mac aqui). Depois precisa clonar o repositório do langtools:

hg clone http://hg.openjdk.java.net/lambda/lambda/langtools

Para compilar esse projeto, de dentro de langtools/make, executamos o ant passando referência para os diretórios de instalação do seu Java 6 e Java 7:

ant -Dboot.java.home=/usr/lib/jvm/java-6-sun -Dtarget.java.home=/algumdiretorio/jdk1.7.0 build-all-tools

Para compilar nosso código que utilize esses recursos do Java 8, precisamos do classes.jar gerado em dist/bootstrap/lib, que contem as classes necessárias para o compilador e também para a execução:

jdk1.7.0/bin/java -cp classes.jar com.sun.tools.javac.Main Classe.java

E para executar:

jdk1.7.0/bin/java -cp classes.jar:. Classe

Você já está pronto para verificar, criticar e comentar. A lista de discussão do projeto Lambda está bastante movimentada. E o que você achou das novidades do Java 8? Comente aqui no Blog e dê sua opinião.

Paulo Silveira ()

Mais sobre o autor

Tags: , , , , ,

22 Respostas para “Trabalhando com closures no Java 8”

  1. Cesimar Xavier

    11. jan, 2011

    Muito bom!!

  2. Pablo Cantero

    11. jan, 2011

    “no caso de haver apenas um método abstrato naquela classe abstrata/interface (single abstract method)”

    Só funcionará se tiver apenas um método abstrato?

    Se Java tivesse um bom suporte para closure, vcs também acham que muitos design patterns irão perder força?

  3. Leandro Silva

    11. jan, 2011

    Booooooa, Paulo! :)

  4. Ricardo Herrmann

    11. jan, 2011

    Respondendo à pergunta do Pablo afirmativamente, o Peter Norvig identificou que, em Lisp ou Dylan, 16 dos 23 patterns do GoF são invisíveis ou mais simples (http://www.norvig.com/design-patterns, slide 10) devido a características destas linguagens. No caso de closures/lambdas/funções de primeira classe, isso inclui Command, Strategy, Template Method e Visitor.

  5. Paulo Silveira

    12. jan, 2011

    @Pablo realmente so funciona com apenas um metodo, ou você toma um “the target type of a lambda conversion has multiple non-overriding abstract methods” Com mais de um, como ele saberia qual é um e qual é outro? Uma sintaxe facilitada para isso nao ficaria muito longe de uma classe anonima.

    E complementando a resposta do @herrmann, realmente vai resolver alguns design patterns, assim como o Java EE 5 eliminou a necessidade de muitos dos antigos Core J2EE Patterns.

  6. Pablo Cantero

    12. jan, 2011

    @Paulo, na verdade eu pensava em blocos mais explícitos, permitindo especificar o método, mas realmente pode ficar muito próximo de uma classe anônima

    @herrmann, obrigado pela resposta! Muito bom saber

  7. Alexandre Gazola

    12. jan, 2011

    Legal!!!

  8. Jazz

    16. jan, 2011

    - Mas o que realmente é proposto do Java 7 para o Java 8 ? Closures é algo certo no Java em sua especificação , ou estamos falando mesmo do uso de Lambda ?

  9. Paulo Silveira

    17. jan, 2011

    @Jazz, a especificação ainda não tem proposta definida, há apenas a afirmação de que o projeto Lambda estará incluso no Java 8:
    http://jcp.org/en/jsr/detail?id=335

    Com as closures funcionarão exatamente no Java 8 ainda é uma dúvida. Esse código que exemplifiquei é ainda uma tentativa, poderá mudar um pouco.

  10. Jazz

    17. jan, 2011

    @Silveira

    Fiz uma pesquisa no assunto sobre Lambda e encontrei um material do InfoQ que não havia lido, esta no link http://bit.ly/hk7RMk Lambdas in Java: An In-Depth Analysis , deu uma clareada, e sobre a JSR 335 Lambda Expressions percebi que em vários fóruns vem sofrendo criticas devido a verbosidade no código discussão http://bit.ly/fQyUvK , mas algo à se evoluir quando efetivada, com certeza.

  11. Paulo Silveira

    17. jan, 2011

    @JazzDuran é isso mesmo, muita discussão. Essa nova proposta é menos verborrágica, bem melhor que essas discutidas em 2008.

  12. Paulo Silveira

    25. jan, 2011

    E pra quem quiser ir além das closures e testar mais recursos futuros, vale ler esse novo post:
    http://www.javarants.com/2011/01/22/using-closures-method-handles-and-extension-methods-in-java-8-jsr-335/

  13. William Cruz Gouvea

    27. jan, 2011

    Achei interessante essa forma abordada no artigo, lembra muito as funções anonimas já usadas em Clojure que por um acaso já são Runnable e Callable!

    Parabens pelo execelente conteudo!

  14. Diogo Silvério

    28. jan, 2011

    Bom abordagem, como de costume.

    Sou sempre a favor da evolução, mas esta feature não me enche os olhos como as outras.

  15. Caio Oliveira

    21. fev, 2011

    Muito interessante. Java menos verboso.

  16. Lennon Jesus

    24. fev, 2011

    Maneiríssimo!

    Aqui funcionou perfeitamente, com exceção do fato de não ter sido gerado nenhum classes.jar.

    Vamos torcer pra eles agilizarem o Java 8.

  17. Ricardo

    20. nov, 2012

    A linguagem ainda tem muito o que melhorar, perde de longe para o vb.net pu c#.

    O fato de nao ter um auto-corretor de codigos quando voce digira uma letra maiuscula ou minuscula faz-se perder muito tempo corrigindo os erros de digitação. Alem disso trabalhar com uma “penca” de chaves ou colchetes só faz confundir ainda mais.

    Enquanto a SUN não mudar isso eu considero uma linguagem inviavel para programadores.

    Up C#!!!!

Trackbacks/Pingbacks

  1. Gilliard Cordeiro » Será que o Java 7/8 faz falta mesmo? - março 16, 2011

    [...] Update: o Paulo Silveira, há um bom tempo já, postou um material bem bacana em português sobre isso no blog da Caelum. [...]

  2. Trabalhando com arquivos do Java IO ao NIO 2 | blog.caelum.com.br - agosto 17, 2011

    [...] maioria recebe uma instância de Path, separando comportamento e dados. Talvez com o futuro Java 8, as closures e defender methods tornarão a interface Path mais amigável, sem depender tanto de métodos [...]

  3. Trabalhando com closures no Java 8 | SWX Softwares - Desenvolvimento e Design Web - setembro 11, 2011

    [...] Fonte: Paulo Silveira/Caelum [...]

  4. Java 7 | Cozinha de Código - outubro 13, 2011

    [...] você fique criando classes anônimas para preencher chamadas de método como o Collections.sort(). Neste blog há uma explicação mais detalhada do funcionamento [...]

  5. Código expressivo e programação funcional em Java com LambdaJ | blog.caelum.com.br - fevereiro 13, 2012

    [...] não esperar as closures do Java 8, conseguimos um pouco de programação funcional utilizando a biblioteca LambdaJ, dando [...]

Deixar uma Resposta