[英]Formatting using DecimalFormat throws exception - “Cannot format given Object as a Number”
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 无法将给定的对象格式化为数字组合框
Illegal Argument Exception 非法参数异常
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 format
方法采用 Object 类型参数,所以这就是为什么我传递了一个 String 对象,它给出了异常
Exception in thread "main" java.lang.IllegalArgumentException: Cannot format given Object as a Number.
线程“main”中的异常 java.lang.IllegalArgumentException:无法将给定的对象格式化为数字。
But when I give double value as argument the program works fine.但是当我给出 double 值作为参数时,程序运行良好。 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
?但是,如果该方法是使用
Object
类型参数定义的,为什么我在传递String
收到异常,而在传递double
String
没有收到异常?
The format()
method of DecimalFormat
is overloaded. DecimalFormat
的format()
方法被重载。
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
.它期望
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.这不是第二个的情况,它接受的类型非常广泛:
Object
和 where 因此在运行时执行对传递的类型的检查。
By providing a argument that is not a double
but a String
, the method invoked is the second one.通过提供一个不是
double
而是String
的参数,调用的方法是第二个。
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
):在
format(Object number, StringBuffer toAppendTo, FieldPosition pos)
,此方法依赖于format(Object number, StringBuffer toAppendTo, FieldPosition pos)
方法,该方法期望作为Number
类( Short
、 Long
、 ... Double
)的实例的number
参数:
@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.但事实并非如此,因为您向它传递了一个
String
实例。
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)
.要解决此问题,请在成功案例中传递一个
double
原语,或者将您的String
转换为Number
的实例,例如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.我建议第一种方式(传递
double
),因为它在已经使用double
基元的代码中更自然。
The second one requires a additional conversion operation from String
to Double
.第二个需要额外的从
String
到Double
转换操作。
If there is any mathematical calculation then using java.math.BigDecimal class's methods are the better choice for accuracy in result and efficient in performance even numbers are too large.如果有任何数学计算,那么使用java.math.BigDecimal类的方法是结果准确性和性能效率的更好选择,即使数字太大。 Using java.math.BigDecimal code :
使用 java.math.BigDecimal 代码:
double externalmark1 = 1.86;
double internalmark2 = 4.0;
System.out.println(String.valueOf((externalmark1*3+internalmark2*1)/4));
System.out.println("------------------------");
BigDecimal decimalValue1 = new BigDecimal((externalmark1*3+internalmark2*1)/4).setScale(2, RoundingMode.HALF_UP);
System.out.println("aggregatemark [direct decimalValue]: "+decimalValue1.toString());
System.out.println("------------------------");
double aggregatemark = (externalmark1*3+internalmark2*1)/4;
System.out.println("aggregatemark [double]: "+aggregatemark);
BigDecimal decimalValue2 = new BigDecimal(aggregatemark).setScale(2, RoundingMode.HALF_UP);
System.out.println("aggregatemark [decimalValue]: "+decimalValue2.toString());
System.out.println("------------------------");
String aggregatemarkStr = String.valueOf((externalmark1*3+internalmark2*1)/4);
System.out.println("aggregatemark [string] : "+aggregatemarkStr);
BigDecimal decimalValue3 = new BigDecimal(aggregatemarkStr).setScale(2, RoundingMode.HALF_UP);
System.out.println("aggregatemark [decimalValue]: "+decimalValue3.toString());
The answer is in the javadoc .答案在javadoc 中。 It says clearly, "The number can be of any subclass of Number", and it says that it throws
IllegalArgumentException
"if number is null or not an instance of Number."它清楚地说,“数字可以是 Number 的任何子类”,并且它说它抛出
IllegalArgumentException
“如果 number 为 null 或不是 Number 的实例”。
(So why don't they just make the parameter a Number
type? Because the class is a subclass of the abstract Format
class that isn't restricted to numeric formatting. The expectation, apparently, is that while the general Format
class has a method with an Object
parameters, subclasses of Format
are expected to limit the parameters to the object types that they can handle, which they have to do at run time.) (那么他们为什么不直接将参数设为
Number
类型?因为该类是不限于数字格式的抽象Format
类的子类。显然,期望是,虽然通用Format
类有一个方法使用Object
参数, Format
子类Object
参数限制为它们可以处理的对象类型,而它们必须在运行时执行。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.