Maintaining precision
There are a few ways of maintaining precision. The first is to completely avoid fixed-precision floating-point binary number types like floats and doubles if your currency uses decimal digits past the point. Here are a few good alternatives:
BigDecimal
java.math.BigDecimal allows you to store precise finitely-long decimal values with ease, but it can be a bit slow.
Use BigDecimals if you need the programming to be easy and the results to be precise, but you're OK with slowness.
long
long can be used to store the amount in cents rather than dollars if you're using US currency.
For other currencies, you can take the reciprocal of the rational GCD of the currency denominations and multiply everything by that when you store it.
Confused? Here's an example of Wolfram|Alpha doing all the hard work of figuring out from the available US currency denominations ($1/100 through $100) that it should multiply US currency by 100. Make sure to use fractions rather than decimals with this.
Use longs if you need a lot of speed and are OK with the drawback that monetary amounts greater than US$92,233,720,368,547,758.07 give completely incorrect results.
Besides being fast by themselves, longs also use a lot less memory and never require garbage collection of themselves, so that's another small speedup for them.
BigInteger
longs can be replaced with java.math.BigIntegers to avoid any overflow problems.
Use this if you want something in between the speed and slowness of the other two with no reasonable chance of ever overflowing.