问题
今天在编程时,产品经理突然和我说,把所有的金额保留两位小数后,传递到前台。一时间,不知道该怎么做,于是,通过百度百科,查找到了DecimalFormat
这个类。
解释DecimalFormat
DecimalFormat
是NumberFormat
的一个具体子类,用于格式化十进制数字,如下代码所示:
import java.math.BigDecimal;
import java.text.DecimalFormat;
/**
* Created By zby on 21:03 2022/5/10
*/
public class StringObject {
public static void main(String[] args) {
DecimalFormat decimalFormat = new DecimalFormat("0.00");
String format = decimalFormat.format(new BigDecimal("2.123"));
System.out.printf("输出结果为:%s", format);
}
}
上述代码的输出结果为:
我们经常使用 DecimalFormat
去格式化数字,其中包括金额。
当然,可以通过DecimalFormat(String pattern)
去创建当前对象,这里的pattern
是设置输出结果的模式。
比如如果输出两位小数,pattern可以为0.00
,如上图所示。
若想输出整数,patter可以为0
,如下图所示:
复现问题
但在项目中使用DecimalFormat
这个类时,出现了错误,错误如下:
通过谷歌翻译得到:无法将给定对象格式化为数字
重点不是这句话,而是为什么无法将给定的对象格式化数字。
如果将String类型转化为BigDecimal
类型的,就不会报错:
为什么会这样呢?
解决问题
通过查看源码得出,DecimalFormat
继承了抽象类NumberFormat
,NumberFormat
继承了抽象类Format
,里面各有format方法
,我们来看看Format类中的format方法
:
public abstract StringBuffer format(Object obj,
StringBuffer toAppendTo,
FieldPosition pos);
这是个未实现的方法,我们点击idea左边的向下箭头,会出现让你惊讶的一幕:
实现该方法的类有很多,而我们今天所说的就DecimalFormat
,我们来看看它的实现方法:
@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");
}
}
你会发现,我们居然找到了上面报错文字: throw new IllegalArgumentException("Cannot format given Object as a Number");
如果你知道instanceof 的话,你就会明白这是该对象是否是某类的实例化对象。这里的有很多包装类,就没有String类和自定义类型,因而,就会出现了错误。所以,它没办法解释格式化String类型的数据。
总结
遇到报错别紧张,查看源码来解析,建议大家使用idea