为何NumberFormat类的format方法会调用子类DecimalFormat的format方法?
解答:这是Java多态与模板方法模式的典型应用
这完全符合面向对象的设计逻辑,核心原因是**多态(运行时类型绑定)**以及Java格式化类库的模板方法设计:
1. currencyInstance的实际类型是DecimalFormat
你通过NumberFormat.getCurrencyInstance()(或同类方法)获取的currencyInstance,虽然声明类型是抽象父类NumberFormat,但运行时实际指向的是DecimalFormat的实例——NumberFormat作为抽象工厂类,负责返回具体的格式化实现子类(DecimalFormat是Java中处理数字/货币格式化的默认实现)。
2. final方法与可重写方法的分工
NumberFormat中的format(long number)是final方法,它的作用是提供统一的调用入口,保证核心流程不可被子类修改。这个方法内部并没有直接实现格式化逻辑,而是调用了另一个重载方法:public final String format(long number) { return format(number, new StringBuffer(), DontCareFieldPosition.INSTANCE).toString(); }- 被调用的
format(long, StringBuffer, FieldPosition)是NumberFormat中定义的可重写方法(甚至是抽象方法),DecimalFormat作为子类重写了这个方法来实现具体的货币格式化逻辑。
3. 运行时的多态绑定
当JVM执行format(number, new StringBuffer(), DontCareFieldPosition.INSTANCE)时,会根据对象的实际运行时类型(也就是DecimalFormat)来查找对应的方法实现,因此会跳转到DecimalFormat中重写的版本,这就是你调试时看到的现象。
简化示例理解
用一个简单的代码片段模拟这个逻辑:
abstract class NumberFormat { public final String format(long number) { // 统一入口,调用子类实现的细节方法 return format(number, new StringBuffer()).toString(); } // 由子类实现具体逻辑 protected abstract StringBuffer format(long number, StringBuffer result); } class DecimalFormat extends NumberFormat { @Override protected StringBuffer format(long number, StringBuffer result) { result.append("格式化后的数字:").append(number); return result; } } // 调用场景 public class Main { public static void main(String[] args) { NumberFormat currencyInstance = new DecimalFormat(); currencyInstance.format(14000); // 实际执行DecimalFormat的format方法 } }
这种设计是模板方法模式的典型应用:父类用final方法固定整体流程,子类重写特定方法定制细节,既保证了流程的一致性,又具备灵活性。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

