简体   繁体   English

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

[英]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. DecimalFormatformat()方法被重载。

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类( ShortLong 、 ... 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 .第二个需要额外的从StringDouble转换操作。

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.

相关问题 使用将字符串格式更改为 NumberFomat,我的例外是无法将给定的对象格式化为数字 - using change String format to NumberFomat and my exception is Cannot format given Object as a Number 使用Android中的DecimalFormat格式化数字 - Format a number using DecimalFormat in Android 使用DecimalFormat格式化双数 - Format double number using DecimalFormat 使用 DecimalFormat 格式化数字 - Formatting numbers using DecimalFormat 无法将给定对象格式化为数字组合框 - Cannot format given Object as a Number ComboBox 线程“主”java.lang.IllegalArgumentException 中的异常:无法将 Object 格式化为数字 - Exception in thread “main” java.lang.IllegalArgumentException: Cannot format given Object as a Number 运行此代码时,我得到了一个不能格式化给定对象的数字异常。 不知道怎么了 - I'm getting a cannot format given object as number exception when I run this code. Not sure what's wrong Java DecimalFormat.format不格式化数字? - Java DecimalFormat.format does not format the number? 使用 DecimalFormat 格式化 0 以包含小数位 - Formatting 0 to include decimal places using DecimalFormat 使用DecimalFormat将双精度格式格式化为String会引发IllegalArgumentException - Formatting a double to String using DecimalFormat is throwing IllegalArgumentException
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM