I use BigDecimal
throughout my application to handle money and percentages. But, I need a way to differentiate usage between the two (for the purpose of rendering them, i.e., in a JTable
). So, my initial thought was to write two classes which behave exactly like BigDecimal
so that I could do instanceof
tests on them. So I wrote this code:
DollarValue.java:
import java.math.BigDecimal;
public class DollarValue extends BigDecimal {
}
PercentValue.java:
import java.math.BigDecimal;
public class PercentValue extends BigDecimal {
}
However, in order to use the constructors (because they cannot be inherited), I you need to manually override every constructor. So, DollarValue.java became a monstrosity:
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
public class DollarValue extends BigDecimal {
public DollarValue(char[] in, int offset, int len) {
super(in, offset, len);
}
public DollarValue(char[] in, int offset, int len, MathContext mc) {
super(in, offset, len, mc);
}
public DollarValue(char[] in) {
super(in);
}
public DollarValue(char[] in, MathContext mc) {
super(in, mc);
}
public DollarValue(String val) {
super(val);
}
public DollarValue(String val, MathContext mc) {
super(val, mc);
}
public DollarValue(double val) {
super(val);
}
public DollarValue(double val, MathContext mc) {
super(val, mc);
}
public DollarValue(BigInteger val) {
super(val);
}
public DollarValue(BigInteger val, MathContext mc) {
super(val, mc);
}
public DollarValue(BigInteger unscaledVal, int scale) {
super(unscaledVal, scale);
}
public DollarValue(BigInteger unscaledVal, int scale, MathContext mc) {
super(unscaledVal, scale, mc);
}
public DollarValue(int val) {
super(val);
}
public DollarValue(int val, MathContext mc) {
super(val, mc);
}
public DollarValue(long val) {
super(val);
}
public DollarValue(long val, MathContext mc) {
super(val, mc);
}
}
But what's worse, in implementation, this didn't work because I use the static BigDecimal
code a lot. To illustrate:
public static void main(String[] args) {
DollarValue dollars = DollarValue.ONE;
DollarValue dollars2 = DollarValue.valueOf(25);
}
throws an error, because DollarValue.ONE
is actually a BigDecimal
, not a DollarValue
and DollarValue#valueOf()
returns a BigDecimal
too.
So now I'm out of ideas. What is the easiest way to distinguish between two implementations of the same class in the way I'm trying to achieve?? This seems like a simple problem...
Edit: Any solution that allows me to automatically differentiate between the two in a renderer will also work. For instance, I need to feed the values to a JTable
and have the JTable
display either a dollar sign $
for money or a percent sign %
for percentages.
I strongly recommend using the Joda-Money library for working with money, rather than trying to reinvent the wheel yourself. Working with money is a common, and tricky, problem. Let other people solve it for you.
It's always a little frustrating to add a new dependency to your project, but when it comes to core utility libraries that provide obvious, but tricky to implement, benefits, it should be a no-brainer. Some other critical libraries are:
There are many other libraries that I could call out as worth using, but you're truly making a mistake if you aren't using these three. While technically "non-standard", like you note, these are so ubiquitous that they aren't far from being conceptually expected parts of a Java developer's toolbelt.