This might look like a repeated question but I tried in all the below links and can't get a proper answer.
Cannot format given Object as a Number ComboBox
But I'm not getting what's wrong. Here is my code
DecimalFormat twoDForm = new DecimalFormat("#.##");
double externalmark = 1.86;
double internalmark = 4.0;
System.out.println(String.valueOf((externalmark*3+internalmark*1)/4));
String val = String.valueOf((externalmark*3+internalmark*1)/4);
String wgpa1=twoDForm.format(val); // gives exception
String wgpa2=twoDForm.format((externalmark*3+internalmark*1)/4)); // works fine
System.out.println(wgpa1);
The format
method takes Object type argument, so that's why I passed a String object which gives exception
Exception in thread "main" java.lang.IllegalArgumentException: Cannot format given Object as a Number.
But when I give double value as argument the program works fine. But if the method is defined with Object
type argument why I'm getting an exception while passing a String
and not getting exception while passing double
?
The format()
method of DecimalFormat
is overloaded.
In the working case, you are invoking :
public final String format(double number)
And in the failing case, you are invoking :
public final String format (Object obj)
The first method takes a very specific argument. It expects a double
.
This is not the case of the second one, which the type accepted is very broad : Object
and where so the check on the type passed is performed at runtime.
By providing a argument that is not a double
but a String
, the method invoked is the second one.
Under the hood, this method relies on the format(Object number, StringBuffer toAppendTo, FieldPosition pos)
method that expects to a number
argument that is an instance of the Number
class (Short
, Long
, ... Double
):
@Override
public final StringBuffer format(Object number,
StringBuffer toAppendTo,
FieldPosition pos) {
if (number instanceof Long ||
number instanceof Integer ||
number instanceof Short ||
number instanceof Byte ||
number instanceof AtomicInteger ||
number instanceof AtomicLong ||
(number instanceof BigInteger && ((BigInteger)number).bitLength () < 64)) {
return format(((Number)number).longValue(), toAppendTo, pos);
} else if (number instanceof BigDecimal) {
return format((BigDecimal)number, toAppendTo, pos);
} else if (number instanceof BigInteger) {
return format((BigInteger)number, toAppendTo, pos);
} else if (number instanceof Number) {
return format(((Number)number).doubleValue(), toAppendTo, pos);
} else {
throw new IllegalArgumentException("Cannot format given Object as a Number");
}
}
But it is not the case as you passed to it a String
instance.
To solve the problem, either pass a double
primitive as in the success case or convert your String
into an instance of Number
such as Double
with Double.valueOf(yourString)
.
I advise the first way (passing a double
) as it is more natural in your code that already uses double
primitives.
The second one requires a additional conversion operation from String
to Double
.