使用DecimalFormat格式化会抛出异常 - “无法将给定对象格式化为数字”

问题描述 投票:5回答:2

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

Cannot format given Object as a Number ComboBox

Illegal Argument Exception

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

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方法采用Object类型参数,这就是我传递给出异常的String对象的原因

线程“main”中的异常java.lang.IllegalArgumentException:无法将给定的Object格式化为数字。

但是当我将double值作为参数时,程序运行正常。但是,如果使用Object类型参数定义方法,为什么我在传递String时遇到异常而在传递double时没有异常?

java exception overloading illegalargumentexception decimalformat
2个回答
12
投票

format()DecimalFormat方法超载。

在工作案例中,您正在调用:

 public final String format(double number)

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

 public final String format (Object obj) 

第一种方法需要一个非常具体的参数。它期待一个double

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

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

在引擎盖下,这种方法依赖于format(Object number, StringBuffer toAppendTo, FieldPosition pos)方法,该方法期望number参数是Number类的实例(ShortLong,... 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");
    }
}

但事实并非如此,因为你传递了一个String实例。

要解决这个问题,要么在成功案例中传递double原语,要么将String转换为Number的实例,例如DoubleDouble.valueOf(yourString)。 我建议第一种方式(传递double),因为它在您的代码中已经使用double原语更自然。 第二个需要从StringDouble的额外转换操作。


1
投票

答案是在javadoc。它清楚地说,“数字可以是Number的任何子类”,它表示如果number为null或不是Number的实例,它会抛出IllegalArgumentException

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

© www.soinside.com 2019 - 2024. All rights reserved.