Eu entendo que BigDecimal é a melhor prática recomendada para representar valores monetários em Java. O que você usa? Existe uma biblioteca melhor que você prefere usar?
Eu entendo que BigDecimal é a melhor prática recomendada para representar valores monetários em Java. O que você usa? Existe uma biblioteca melhor que você prefere usar?
Respostas:
BigDecimal
todo o caminho. Já ouvi falar de algumas pessoas criando suas próprias classes Cash
ou Money
que encapsulam um valor em dinheiro com a moeda, mas sob a pele ainda é umBigDecimal
, provavelmente com BigDecimal.ROUND_HALF_EVEN
arredondamento.
Edit: Como Don menciona em sua resposta , existem projetos de código aberto como tempo e dinheiro , e embora eu os aplauda por tentar evitar que os desenvolvedores tenham que reinventar a roda, eu simplesmente não tenho confiança suficiente em uma biblioteca pré-alfa para usar em um ambiente de produção. Além disso, se você vasculhar sob o capô, verá que eles BigDecimal
também usam .
Pode ser útil para as pessoas que chegam aqui pelos mecanismos de pesquisa saberem sobre o JodaMoney: http://www.joda.org/joda-money/ .
BigDecimal
sob o capô!
Não estou expressando minha opinião aqui, mas existem argumentos muito bons contra BigDecimal que alguém provavelmente deveria jogar fora:
http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money/
Uma biblioteca conveniente que encontrei anteriormente é a biblioteca Joda-Money . Uma de suas implementações é de fato baseada em BigDecimal. É baseado no ISO-4217 especificação para moedas e pode suportar uma lista de moedas personalizada (carregada via CVS).
Esta biblioteca possui um pequeno número de arquivos que podem ser acessados rapidamente se forem necessárias modificações. Joda-Money é publicado sob a licença Apache 2.0.
Se você estiver usando apenas dólares e centavos, eu usaria um longo (compensado por 2 casas decimais). Se você precisar de mais detalhes, o grande número decimal pode ser o melhor.
De qualquer forma, provavelmente estenderia a classe para ter um .toString () que usa o formato correto e como um lugar para colocar outros métodos que possam surgir (por um longo tempo, a multiplicação e a divisão serão incorretas se o decimal for 't ajustado)
Além disso, se você usar definir sua própria classe e interface, poderá substituir a implementação à vontade.
BigDecimal
ou outra representação de ponto fixo é o que geralmente é necessário para dinheiro.
As representações e cálculos de ponto flutuante ( Double
, Float
) são inexatos, levando a resultados errôneos.
Você tem que ter muito cuidado ao lidar com tempo e dinheiro.
Quando você está trabalhando com dinheiro, espero que todos saibam que nunca deve usar float ou double.
Mas não tenho certeza sobre BigDecimal.
Na maioria dos casos, você ficará bem se apenas manter o controle dos centavos em um int ou longo. Desta forma, você nunca lida com uma casa decimal.
Você só exibe dólares quando o imprime. Sempre trabalhe com centavos internos usando números inteiros. Isso pode ser complicado se for necessário dividir ou usar Math.abs ().
No entanto, você pode se importar com meio centavo, ou mesmo um centésimo de centavo. Não sei qual é a boa maneira de fazer isso. Você só precisa lidar com um milésimo de centavos e usar um longo. Ou talvez você seja forçado a usar BigDecimal
Eu faria muito mais leitura sobre isso, mas ignore todo mundo que começa a falar sobre usar um float ou dobre para representar dinheiro. Eles estão apenas procurando problemas.
Sinto que meu conselho não está completo, então, por favor, pense mais nele. Você está lidando com tipos perigosos!
Criar uma classe Money é o caminho a percorrer. Usando BigDecimal (ou mesmo um int) por baixo. Em seguida, usando a classe Currency para definir a convenção de arredondamento.
Infelizmente, sem sobrecarregar o operador, o Java torna bastante desagradável a criação desses tipos básicos.
Existe uma biblioteca melhor, tempo e dinheiro . IMO, é muito superior às bibliotecas fornecidas pelo JDK para representar esses 2 conceitos.
Definitivamente não é BigDecimal. Existem tantas regras especiais para arredondamento e apresentação que você precisa se preocupar.
Martin Fowler recomenda a implementação de uma classe Money dedicada para representar valores de moeda e que também implementa regras para conversão de moeda.
Ei, aqui está um artigo muito interessante sobre BigDecimal, e um exemplo ilustrativo de por que às vezes é usado em vez de duplos. Tutorial BigDecimal .
Você pode usar a classe DecimalFormat ao exibir um valor de moeda. Ele fornece suporte à localização e é bastante extensível.
Eu encapsularia BigDecimal na classe Money, que também tem uma moeda, como alguém mencionado acima. O importante é que você faça uma quantidade extrema de testes de unidade e principalmente se estiver trabalhando com moedas diferentes. Também é uma boa ideia se você adicionar um construtor conveniente que pega uma string ou um método de fábrica que faz o mesmo, para que você possa escrever seus testes da seguinte forma:
assertEquals(Money.create("100.0 USD").add("10 GBP"),Money.create("116 USD"));
Sempre há restrições e especificidades envolvidas. Qualquer pessoa sem experiência suficiente para avaliar as questões sutis descritas no artigo a seguir deve reconsiderar seriamente antes de lidar com dados financeiros do mundo real:
http://lemnik.wordpress.com/2011/03/25/bigdecimal-and-your-money
BigDecimal dificilmente é a única representação correta ou a única peça do quebra-cabeça. Dadas certas condições, usar uma classe Money apoiada por centavos armazenados como um inteiro pode ser suficiente e seria muito mais rápido do que BigDecimal. Sim, isso implica o uso de dólares como moeda e limites de valores, mas essas restrições são perfeitamente aceitáveis para muitos casos de uso e todas as moedas têm casos especiais para arredondamento e sub-denominações de qualquer maneira, portanto, não há uma solução "universal".