使用 DecimalFormat 格式化会抛出异常 - "Cannot format given Object as a Number"
Formatting using DecimalFormat throws exception - "Cannot format given Object as a Number"
这可能看起来像一个重复的问题,但我尝试了以下所有链接,但无法得到正确的答案。
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 对象,它给出了异常
Exception in thread "main" java.lang.IllegalArgumentException: Cannot
format given Object as a Number.
但是当我给出双精度值作为参数时程序工作正常。但是,如果该方法是用 Object
类型参数定义的,为什么我在传递 String
时出现异常,而在传递 double
时没有出现异常?
答案就在javadoc中。它说得很清楚,"The number can be of any subclass of Number",它说它抛出 IllegalArgumentException
"if number is null or not an instance of Number."
(那么他们为什么不直接将参数设为 Number
类型呢?因为 class 是抽象 Format
[=24 的子class =] 不限于数字格式。显然,期望是,虽然一般 Format
class 有一个带有 Object
参数的方法,但 subclasses Format
的人希望将参数限制为他们可以处理的对象类型,他们必须在 运行 时间完成。)
DecimalFormat
的 format()
方法被重载。
在工作案例中,您正在调用:
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
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
实例。
要解决这个问题,要么像成功案例那样传递一个 double
原语,要么将你的 String
转换成 Number
的实例,例如 Double
和 Double.valueOf(yourString)
.
我建议第一种方式(传递 double
),因为它在已经使用 double
原语的代码中更自然。
第二个需要额外的从String
到Double
的转换操作。
如果有任何数学计算那么使用java.math.BigDecimalclass的方法是更好的选择结果的准确性和性能效率偶数太大了。
使用 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());
这可能看起来像一个重复的问题,但我尝试了以下所有链接,但无法得到正确的答案。
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 对象,它给出了异常
Exception in thread "main" java.lang.IllegalArgumentException: Cannot format given Object as a Number.
但是当我给出双精度值作为参数时程序工作正常。但是,如果该方法是用 Object
类型参数定义的,为什么我在传递 String
时出现异常,而在传递 double
时没有出现异常?
答案就在javadoc中。它说得很清楚,"The number can be of any subclass of Number",它说它抛出 IllegalArgumentException
"if number is null or not an instance of Number."
(那么他们为什么不直接将参数设为 Number
类型呢?因为 class 是抽象 Format
[=24 的子class =] 不限于数字格式。显然,期望是,虽然一般 Format
class 有一个带有 Object
参数的方法,但 subclasses Format
的人希望将参数限制为他们可以处理的对象类型,他们必须在 运行 时间完成。)
DecimalFormat
的 format()
方法被重载。
在工作案例中,您正在调用:
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
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
实例。
要解决这个问题,要么像成功案例那样传递一个 double
原语,要么将你的 String
转换成 Number
的实例,例如 Double
和 Double.valueOf(yourString)
.
我建议第一种方式(传递 double
),因为它在已经使用 double
原语的代码中更自然。
第二个需要额外的从String
到Double
的转换操作。
如果有任何数学计算那么使用java.math.BigDecimalclass的方法是更好的选择结果的准确性和性能效率偶数太大了。 使用 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());