关于java:使用DecimalFormat格式化会引发异常-“无法将给定对象格式化为数字”

Formating using DecimalFormat throws exception - “Cannot format given Object as a Number”

这可能看起来像是一个重复的问题,但是我尝试了以下所有链接,但没有得到正确的答案。

无法将给定对象格式化为数字组合框

非法论证例外

但是我没有错。 这是我的代码

1
2
3
4
5
6
7
8
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);

format方法采用对象类型参数,因此这就是为什么我传递了一个给出异常的String对象的原因

Exception in thread"main" java.lang.IllegalArgumentException: Cannot
format given Object as a Number.

但是,当我给出double值作为参数时,程序运行良好。 但是,如果该方法是用Object类型参数定义的,为什么我在传递String时得到异常而在传递double时却没有异常?


DecimalFormatformat()方法已重载。

在工作情况下,您正在调用:

1
 public final String format(double number)

在失败的情况下,您正在调用:

1
 public final String format (Object obj)

第一种方法有一个非常具体的参数。它要求double

第二种情况不是这样,第二种情况接受的类型非常广泛:Object,因此对传递的类型的检查在运行时执行。

通过提供一个不是double而是String的参数,调用的方法是第二个方法。

在幕后,此方法依赖于format(Object number, StringBuffer toAppendTo, FieldPosition pos)方法,该方法期望作为Number类(ShortLong,... double)的实例的Number自变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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");
    }
}

但是情况并非如此,因为您将其传递给String实例。

要解决此问题,可以像成功情况一样传递double原语,或者将String转换为Number的实例,例如doubleDouble.valueOf(yourString)
我建议采用第一种方法(传递double),因为它在已经使用double原语的代码中更为自然。
第二个要求从Stringdouble的附加转换操作。


答案在javadoc中。它清楚地说:"数字可以是Number的任何子类",并且说,如果number为null或不是Number的实例,则抛出IllegalArgumentException

(所以为什么他们不只是将参数设置为Number类型呢?因为该类是抽象Format类的子类,所以不限于数字格式。显然,期望的是,通用< x2>类有一个带有Object参数的方法,Format的子类应该将参数限制为它们可以处理的对象类型,而这些对象类型必须在运行时执行。)