avapractices.com/topic/TopicAction.do?Id=13"> www.javapractices.com . Modifications include the following:
- JPA annotations have been added to make the class persistent.
- Private setters are provided for JPA to work correctly (the class should still be treated as immutable).
- Operations with {@link DecimalQuantity} have been introduced.
- validateState() method has been modified to remove the the scale restriction of the currency. This allows arbitrary precision for Money values. This is needed for some applications, for example trading, where say a US stock price must be specified with 4 decimal precision.
- Scaling operations in times() methods have been commented out, again to get arbitrary precision amounts. A method called scaleToCurrency() has been introduced if scaling to currency is desired.
- roundToInterval() method has been added to support financial applications.
Original Documentation
Represent an amount of money in any currency.
This class assumes decimal currency, without funky divisions like 1/5 and so on. Money objects are immutable. Like {@link BigDecimal}, many operations return new Money objects. In addition, most operations involving more than one Money object will throw a MismatchedCurrencyException if the currencies don't match.
Decimal Places and Scale
Monetary amounts can be stored in the database in various ways. Let's take the example of dollars. It may appear in the database in the following ways :
- as 123456.78, with the usual number of decimal places associated with that currency.
- as 123456, without any decimal places at all.
- as 123, in units of thousands of dollars.
- in some other unit, such as millions or billions of dollars.
The number of decimal places or style of units is referred to as the scale by {@link java.math.BigDecimal}. This class's constructors take a BigDecimal, so you need to understand it use of the idea of scale.
The scale can be negative. Using the above examples:
Number | Scale |
123456.78 | 2 |
123456 | 0 |
123 (thousands) | -3 |
Note that scale and rounding are two separate issues. In addition, rounding is only necessary for multiplication and division operations. It doesn't apply to addition and subtraction.
Operations and Scale
Operations can be performed on items having different scale. For example, these operations are valid (using an ad hoc symbolic notation):
10.plus(1.23) => 11.23 10.minus(1.23) => 8.77 10.gt(1.23) => true 10.eq(10.00) => true
This corresponds to typical user expectations. An important exception to this rule is that {@link #equals(Object)} is sensitive to scale (while{@link #eq(Money)} is not) . That is,
10.equals(10.00) => false
Multiplication, Division and Extra Decimal Places
Operations involving multiplication and division are different, since the result can have a scale which exceeds that expected for the given currency. For example
($10.00).times(0.1256) => $1.256
which has more than two decimals. In such cases,
this class will always round to the expected number of decimal places for that currency. This is the simplest policy, and likely conforms to the expectations of most end users.
This class takes either an int or a {@link BigDecimal} for itsmultiplication and division methods. It doesn't take float or double for those methods, since those types don't interact well with BigDecimal. Instead, the BigDecimal class must be used when the factor or divisor is a non-integer.
The {@link #init(Currency,RoundingMode)} method must be called at least once before using the other members of this class. It establishes your desired defaults. Typically, it will be called once (and only once) upon startup.
Various methods in this class have unusually terse names, such as {@link #lt}and {@link #gt}. The intent is that such names will improve the legibility of mathematical expressions. Example :
if (amount.lt(hundred)) { cost = amount.times(price); }