Haven't been able to find appropriate solution in web, therefore I thought to ask if my way of using a java format is correct.
1) In the NumberFormat.java documentation it says that
Number formats are generally not synchronized. It is recommended to create separate format instances for each thread.
We have been using format objects (statically initialized) in a multi-threaded environment with no issues so far. Is it maybe because once the formats are defined, we their state is not changed (ie, no setters are called afterwards)
2) I now need to define a new format which should output either one or two significant digits after comma, depending on some extra logic. The way i did it was to define a new format wrapper and delegate to two distinct DecimalFormat depending on the case in the overwritten #format(double, StringBuffer, FieldPosition) method. Here is the code for that:
private final NumberFormat FORMAT = new DecimalFormat() {
private final NumberFormat DECIMAL_FORMAT = new DecimalFormat("0.##");
private final NumberFormat DECIMAL_FORMAT_DIGIT = new DecimalFormat(
"0.0#");
public StringBuffer format(double number, StringBuffer result, java.text.FieldPosition fieldPosition) {
if ((number >= 10 && Math.ceil(number) == number)) {
return DECIMAL_FORMAT.format(number, result, fieldPosition);
} else {
return DECIMAL_FORMAT_DIGIT.format(number, result, fieldPosition);
}
}
};
Is it the best practice? I have concerns about not actually using the wrapper class (it serves only to comply with the NumberFormat interface and delegates all the work on inner formats). I do not want to call DecimalFormat#applyPattern() as i think this would compromize the volatile concurrency.
Thanks
- We have been using format objects (statically initialized) in a multi-threaded environment with no issues so far. Is it maybe because once the formats are defined, we their state is not changed (ie, no setters are called afterwards)
It is impossible to say exactly why you haven't seen any issues, since we don't know exactly how you are using them. Off the top of my head, a few reasons might be:
DecimalFormat
which use the mutable instance variables;The thing about synchronization issues, as I saw somebody else comment yesterday, is that you aren't guaranteed to see an issue if you don't synchronize; it's just that you're not guaranteed not to see them either.
The point is that if you're not applying synchronization, you are at the whim and mercy of any number of subtle changes that you may just be totally unaware of. Today it works, tomorrow it doesn't; you'll have one almighty job working out why.
- Is it the best practice?
There are a couple of problems I can think of here:
By extending the class, you risk falling foul of the fragile base class problem.
In a nutshell, unless you are actually calling the public StringBuffer format(double, StringBuffer, java.text.FieldPosition )
method on your DecimalFormat
instance explicitly, you can't reliably know whether your overridden method is actually the one called: a change to the implementation of the base class (DecimalFormat
) could change the logic you are relying upon to call that method.
You have three mutable instances - FORMAT
, DECIMAL_FORMAT
and DECIMAL_FORMAT_DIGIT
- which have all manner of setters to change their behaviour.
You should propagate all of those setters to all of the instances, in order that they behave consistently, e.g. if you call setPositivePrefix
on FORMAT
, you should also call the same method on DECIMAL_FORMAT
and DECIMAL_FORMAT_DIGIT
.
Unless you actually need to pass FORMAT
as a parameter to a method, it would be much more robust if you just defined a plain old method which invokes your logic: basically, move the method you are overriding out of the anonymous subclass:
private static StringBuffer formatWithSpecialLogic(double number, StringBuffer result, java.text.FieldPosition fieldPosition) {
Then you have to call that method explicitly if you want to use that special logic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With