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

Java 使用DecimalFormat进行格式化会引发异常-“;无法将给定对象格式化为数字;,java,exception,overloading,illegalargumentexception,decimalformat,Java,Exception,Overloading,Illegalargumentexception,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 = S

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

但我不明白怎么回事。这是我的密码

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中的异常:无法 将给定对象格式化为数字。

但当我给出双值作为参数时,程序运行良好。但是如果方法是用
对象
类型参数定义的,那么为什么我在传递
字符串时得到异常,而在传递
双精度
时没有得到异常?

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

(那么,他们为什么不把参数设为
Number
类型呢?因为该类是抽象类的一个子类,不受数字格式的限制。显然,我们的期望是,虽然通用
格式
类有一个带有
对象
参数的方法,但是
格式
的子类是可扩展的。)将参数限制为它们可以处理的对象类型,这是它们在运行时必须执行的。)

DecimalFormat的
format()
方法重载

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

 public final String format(double number)
在失败的情况下,您将调用:

 public final String format (Object obj) 
第一个方法接受一个非常特定的参数。它需要一个
double

第二种情况并非如此,它接受的类型非常广泛:
Object
,因此在运行时对传递的类型进行检查。

通过提供一个不是
双精度
而是
字符串
的参数,调用的方法是第二个。

在引擎盖下,此方法依赖于
格式(对象编号、StringBuffer to Appendto、FieldPosition pos)
方法,该方法需要一个
number
参数,该参数是
number
类的一个实例(
Short
Long
,…
Double
):

@覆盖
公共最终StringBuffer格式(对象编号,
StringBuffer toAppendTo,
现场位置(pos){
if(长| |的数字实例)
整数| |的数字实例
短| |的数字实例
字节| |的数字实例
原子整数的数字实例||
原子数实例||
(BigInteger的数字实例&((BigInteger)数字)。位长度()<64){
返回格式(((数字)Number).longValue(),toAppendTo,pos);
}else if(BigDecimal的数字实例){
返回格式((BigDecimal)数字,toAppendTo,pos);
}else if(BigInteger的数字实例){
返回格式((BigInteger)编号,toAppendTo,pos);
}else if(数字实例数字){
返回格式(((数字)Number.doubleValue(),toAppendTo,pos);
}否则{
抛出新的IllegalArgumentException(“无法将给定对象格式化为数字”);
}
}
但当您向其传递一个
字符串
实例时,情况并非如此。

要解决此问题,请像在成功案例中一样传递
double
原语,或者将
String
转换为
Number
的实例,例如
double
double.valueOf(yourString)

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

第二种方法需要额外的从
String
Double

的转换操作,如果有任何数学计算,则使用java.math.bigdecim类的方法在结果准确性和性能方面是更好的选择,即使数字太大。 使用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());

你好,YCF!我开始好多了!太棒了。你好吗?:)非常高兴,就像上次一样:)
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());