Reputation: 31730
After a lot of messing around I came up with the following code to convert any Number subclass into a BigDecimal.
I'm not convinced however that this code is fully correct. I'm certainly not happy about how verbose it is!
Is there a better way of doing this, and are there any pitfalls to this approach of which I need to be aware (other than floating point imprecise representation issues of which I'm already aware)?
public DecimalSpec setValue (Number value) {
if (value instanceof Double) {
if ((((Double) value).isNaN ())
|| (((Double) value).isInfinite ())) {
throw new IllegalArgumentException ("Infinite or NaN values not allowed");
}
}
this.value = new BigDecimal (value.toString ());
return this;
}
Upvotes: 0
Views: 2851
Reputation: 5208
I'm not aware of any way to write it in less code, as in some method that would shortcut part of the code. However, I'd probably overload the method for Double
, or let BigDecimal
throw a NumberFormatException
instead.
Letting BigDecimal
do the work:
/** May throw NumberFormatException or NullPointerException. */
public DecimalSpec setValue (Number value) {
this.value = new BigDecimal (value.toString ());
return this;
}
Overloading for Double
:
/** May throw NullPointerException. */
public DecimalSpec setValue (Number value) {
this.value = new BigDecimal (value.toString ());
return this;
}
/** May throw NullPointerException or IllegalArgumentException. */
public DecimalSpec setValue (Double value) {
if (value.isNaN () || value.isInfinite ()) {
throw new IllegalArgumentException ("Infinite or NaN values not allowed");
}
return this.setValue ((Number) value);
}
Upvotes: 2
Reputation: 29856
I think you have a design problem. Make setValue
take a BigDecimal
to begin with. Then the code that converts other types to BigDecimal
can be elsewhere in your code. You'll have the freedom to overload the BigDecimal
conversion for various types, and you can do a conversion to BigDecimal
based specifically on the input type.
E.g.,
public class BigDecimalConverter {
public static toBigDecimal(int i) { ... }
public static toBigDecimal(double i) { ... }
...
}
Then
public DecimalSpec setValue (BigDecimal value) {
this.value = value;
return this;
}
and
decimalSpec.setValue(BigDecimalConverter.toBigDecimal(myNumber));
Not perfect, of course, but that's the general idea. One piece of code should never do too much work. If it's necessary to accept an unknown type for conversion at some point, you might consider a converter interface
and then a factory class (might not be the right pattern name) to give you the right one.
Upvotes: 1