0
0

More than 3 years have passed since last update.

JavaのBigDecimalでハマらないために

Last updated at Posted at 2019-11-21

同僚がBigDecimalの扱いでハマったのでメモ。

イミュータブル(Immutable)とは

変数の値オブジェクトを操作するとき、その変数オブジェクト自身の値を書き換えれることを「ミュータブル」、書き換えれないことを「イミュータブル」といいます。Javaの場合、intやdoubleCalendarはミュータブル、Stringはイミュータブルになります。

BigDecimalはどっち?

BigDecimalのAPIドキュメント
https://docs.oracle.com/javase/jp/8/docs/api/java/math/BigDecimal.html

足し算をする add メソッドについて見てみましょう。

/**
値が(this+augend)でスケールがmax(this.scale(), augend.scale())であるBigDecimalを返します。
パラメータ: augend - このBigDecimalに加算する値。
戻り値: this + augend
*/
public BigDecimal add(BigDecimal augend)

さて、次のコードの出力結果はいくつになるでしょう?

public static void main(String args[]) {
    BigDecimal a = new BigDecimal("1");
    BigDecimal b = new BigDecimal("2");
    a.add(b);
    System.out.println(a);
}

出力結果。

1

あれ?3じゃないの?と思ったあなた。APIドキュメントの大事な一文を見落としていますよ。

変更が不可能な、任意精度の符号付き10進数です。

つまり、このコードは、a+b の値を持つBigDecimalのオブジェクトを新たに作って、そのオブジェクトを返すという意味だったのです。a自身の値は一切変更されないのです。

a.add(b);

DBから数値をBigDecimalで取り出してお金の計算をするコードだったのだけれど、addなどのメソッドの結果を変数に代入せず処理を進めて、物の見事にバグっていました。

コードの字面だけではイミュータブルなことを見抜けない……なんとも厄介なバグなのでした。

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0