Java 中继承的缺点

2025年5月12日 | 阅读 3 分钟

继承面向对象编程 (OOP) 的四大基本组成部分之一。通过继承,子类可以获取父类的所有字段和方法。

该特性使开发人员能够重用代码块,并创建可维护和可扩展的程序,从而实现有效的 Java 开发。继承模型也带来了一些特定的弊端,包括复杂的代码结构以及类之间加强的关联。

1. 增加父类与子类之间的耦合度

由于继承,父子类关系变得紧密联系。对父类的修改可能会影响到每一个子类,从而可能引入不必要的 bug。

例如:所有需要使用父类方法的子类,在父类方法被修改或损坏后都必须进行更新。继承结构会创建难以维护且脆弱的代码库。

2. 继承不必要的属性和方法

子类会继承超类的所有公共和受保护的成员,即使它们并不需要。这可能导致子类的内存浪费和不必要的复杂性。

在这里,Bicycle 类继承了 startEngine() 方法,尽管这对于自行车来说并不合理。

3. 降低灵活性并强制形成僵化的继承体系

继承强制执行严格的层级关系,这对于某些应用程序来说可能不是最佳方案。当需要灵活性时,组合(使用其他类的对象而不是继承)通常是更好的选择。

在这里,Car "拥有"(has-a)一个 Engine,而不是继承 Engine,这使得关系更加灵活。

4. 增加复杂性,使调试困难

在深度继承的类结构中,调试可能变得具有挑战性,因为子类中的一个问题可能源于多层之上的某个继承方法。这可能导致“意大利面条式代码”,使追踪错误更加困难。

5. 性能开销

继承机制需要额外的步骤来解析方法,这会带来微小的系统性能下降。现代 Java 虚拟机在处理继承时效率很高,但对性能至关重要的应用程序需要控制继承的使用,以防止执行速度降低。

6. 破坏封装

继承的公共访问性质允许子类查看超类的实现细节,这违背了封装原则。超类中的受保护变量和方法可以通过子类进行修改,这可能导致意外的结果。

7. 紧耦合导致重构困难

如果修改了超类,所有子类都会受到影响,这使得重构变得困难。基类中的微小更改可能导致多个派生类出现意外的副作用,增加维护的复杂性。

8. 单元测试的困难

当子类依赖于超类的继承方法时,测试子类会变得更加困难。模拟和测试这些依赖项需要额外的努力,使得单元测试变得复杂。


下一主题BiFunction Java 8