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

新手上路,请多包涵

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

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

非法参数异常

但我不明白哪里出了问题。这是我的代码

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 方法采用对象类型参数,所以这就是为什么我传递了一个给出异常的字符串对象

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

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

原文由 Arun Sudhakaran 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

—的 DecimalFormat format() 方法被重载。

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

  public final String format(double number)

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

  public final String format (Object obj)

第一种方法采用非常具体的参数。它期望一个 double

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

通过提供一个不是 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 ):

 @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 实例时,情况并非如此。

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 DoubleDouble.valueOf(yourString)

我建议第一种方式(传递 double ),因为它在已经使用 double 原语的代码中更自然。

第二个需要从 StringDouble 的额外转换操作。

原文由 davidxxx 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果有任何数学计算,那么使用 java.math.BigDecimal 类的方法是结果准确性和性能效率的更好选择,即使数字太大。 使用 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());

原文由 Jimmy 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题