Money API: programação avançada com os novos recursos do Java 8
Saiba como utilizar um dos destaques do Java 9 em conjunto com os principais recursos do Java 8.
Este Artigo faz parte da Revista Java Magazine 151 Ver Revista
Artigos Java Money API: programação avançada com os novos recursos do Java 8
Por que eu devo ler este artigo:Neste artigo você vai aprender a desenvolver sistemas que manipulam valores monetários sem precisar lidar com os tipos Double, Float ou BigDecimal, comumente utilizados para suportar esse tipo de requisito. Isso é possível porque o Java 9 será lançado com a Money API, uma nova especificação que possibilitará uma forma mais simples, elegante e profissional de lidar com valores e moedas.
Além de analisar a Money API, apresentaremos um resumo das principais novidades da API do Java 8, que foi largamente utilizada na construção dessa especificação. A partir disso, veremos diversos exemplos e códigos que demonstrarão problemas do mundo real, e como esta nova API facilita a resolução de cada um.
Em qualquer sistema, seja ele financeiro, jurídico ou contábil, é comum trabalharmos com valores monetários para representar os preços de ações, de produtos e cálculos financeiros complexos, por exemplo. Para isso, ao longo dos anos a comunidade adotou como padrão de mercado os tipos Double, Float ou BigDecimal. Contudo, visto que não são tipos voltados para essa necessidade, muitos desenvolvedores passaram por diferentes problemas durante a implementação, como:
· Imprecisão no arredondamento;
· Conversão de moedas manual e limitada;
· Passos desnecessários para operações simples, como soma e subtração;
· Dificuldade na realização de operações mais avançadas, como ordenações e agrupamentos, bem como estatísticas básicas (ex.: média, valores mínimo e máximo, entre outras).
Essa forma padronizada que usamos até hoje se deu pela inexistência de uma API formal do Java para manipular valores em um sistema. Se você já precisou usar o tipo BigDecimal ou o Double para representar preço em alguma aplicação, provavelmente você já passou pelos problemas supracitados, correto?
Como esse problema de manipulação de valores é recorrente, o Java 9 está trazendo uma opção nativa para o tratamento de dados monetários, a Money API, cuja especificação está sendo desenvolvida sob a JSR 354.
Uma introdução sobre a Money API foi feita na edição 145 da Java Magazine. Este artigo, por sua vez, cobrirá os assuntos não abordados e mais avançados. Ainda assim, caso não tenha acompanhado a edição anterior, não se preocupe, pois analisaremos cada exemplo detalhadamente.
Ademais, é válido ressaltar que o foco do nosso estudo, obviamente, estará nos recursos da Money API, mas para melhorar o aprendizado, vamos implementar o código dos exemplos em classes simples usando o framework JUnit, que permitirá que criemos métodos de teste que facilitarão a visualização dos resultados esperados.
Revisando as novidades do Java a partir da versão 8
Antes de iniciarmos nosso estudo sobre a Money API, é importante relembrarmos algumas características que foram adicionadas no Java 8. Precisamos deste conhecimento porque a Money API utiliza amplamente diversos destes novos recursos em sua própria API e por esse motivo não é possível utilizá-la em versões anteriores do Java.
Sabendo disso, vamos revisar, de forma breve, as seguintes novidades: Lambda Expression, Predicate, Functions, Suppliers, Optionals e Stream. Após o estudo dessas features estaremos prontos para aprender sobre os recursos avançados da tecnologia foco deste artigo.
Expressões lambda
Uma das principais mudanças adicionadas na versão 8 do Java é a possibilidade de trabalharmos com expressões Lambda. De forma resumida, uma expressão lambda é uma função que apresenta basicamente duas características principais: podem possuir ou não parâmetros em sua assinatura e seus tipos podem ser explícitos ou podem ser omitidos, permitindo que o compilador consiga inferir os tipos desejados.
As expressões lambda foram inseridas no Java para que a linguagem pudesse ganhar algumas características de linguagens funcionais, como Scala e Clojure. O grande destaque das expressões lambda está na simplicidade de escrita e leitura de funções, que até então eram extremamente verbosas.
Na Listagem 1 temos um exemplo simples e clássico do uso de threads. Neste código, através de uma classe anônima, criamos uma thread da forma padrão, para impressão de uma frase.
Listagem 1. Código que implementa threads da forma padrão para imprimir uma mensagem, usando classe anônima.
public void imprimeMensagemUtilizandoThreads() throws Exception {
System.out.println("Thread de forma clássica");
Note que o método envolve apenas a interface Runnable e a classe Thread. Contudo, mesmo para um código básico, foi necessária a escrita de muitas linhas.
Na Listagem 2 apresentamos o mesmo exemplo, mas desta vez declarando uma expressão lambda.
Listagem 2. Código que utiliza threads e expressões lambda para imprimir uma mensagem, sem utilizar classe anônima.
public void imprimeMensagemUtilizandoThreadsComLambda() throws Exception {
Runnable runnable = () -> System.out.println("Thread utilizando Lambda!");
Este método possui o mesmo comportamento que o apresentado na listagem anterior, mas com um código mais limpo e de fácil leitura e compreensão. Ao analisá-lo, percebemos a presença dos parênteses após o operador de igualdade, o que representa a declaração da função que está sendo criada.
No código dessa listagem, o compilador entende que o método System.out.println() deverá ser executado dentro do método run() da interface Runnable, usando o recurso de expressão lambda.
Lembra que o método run() da interface Runnable não recebe parâmetro e não retorna nenhum valor (void)? Note que a função que criamos respeita exatamente essa assinatura. Os parênteses vazios sinalizam a criação de uma função que não possui parâmetros e também não retorna valor; consequentemente, nossa função também será void.
Outra característica importante das expressões lambda é que podemos passar uma expressão lambda como parâmetro para um método, reduzindo ainda mais o tamanho do código e tornando-o mais legível e expressivo. Como exemplo, na Listagem 3 temos o mesmo método implementado com a classe Thread, mas que passa a função lambda diretamente como parâmetro para o construtor dessa classe.