Java继承与类层次结构的核心概念

Java中extends并非复制父类代码,而是建立继承关系以获得访问权限;private成员不被继承,super仅调用直接父类成员,Object为隐式父类无需显式声明,继承优先级高于接口实现。

Java中extends关键字的实际作用不是“复制父类代码”

很多人初学时误以为extends会让子类“拥有”父类的字段和方法副本,其实子类只是获得访问权限(受访问修饰符限制),且所有实例共享同一套继承链上的行为逻辑。真正决定能否调用的是编译期类型检查 + 运行时动态绑定。

关键点:

  • private成员不会被继承,子类无法直接访问,哪怕同包也不行
  • protected成员可被子类访问,无论是否在同一包
  • 默认(包级私有)成员仅在同包子类中可见
  • 构造器不会被继承

    ,但必须显式或隐式调用super()

为什么Object是所有类的隐式父类,但不能写class A extends Object

Java语言规范强制要求:如果类声明中没有extends子句,则默认以Object为直接父类。手动写extends Object语法合法,但毫无必要,且会干扰一些依赖“显式继承关系”的工具(如某些序列化框架或Lombok插件)。

注意以下两种写法等价:

class Dog { }
class Dog extends Object { }

但后者在IDE中可能触发警告,且掩盖了真正有意义的继承意图。

多层继承下super只能访问直接父类成员

super不是“向上找任意祖先”,它只解析到**直接父类**的字段、方法和构造器。若想跳过一层调用祖父类方法,Java不提供语法支持——必须由父类暴露该能力(例如通过protected方法封装)。

常见错误场景:

  • GrandChild中写super.super.method() → 编译失败,语法非法
  • 父类未将祖父类方法用protected重新暴露 → 子类无法间接调用
  • 重写链中某一级把方法改成了private → 断裂,后续子类彻底不可见

接口与抽象类混用时,类层次结构的实际优先级

一个类可以extends一个类,同时implements多个接口,但继承关系永远优先于实现关系。这意味着:

  • 字段和方法查找顺序:本类 → 父类 → 祖父类… → Object;接口中的默认方法只在类层次查不到时才参与解析
  • 若父类和接口都定义了同签名的default方法,必须在子类中显式重写,否则编译报错
  • 接口不能有构造器,因此super()永远指向继承链上的类,而非接口

真正容易被忽略的是:当父类方法抛出异常,而子类实现的接口默认方法也抛相同异常时,JVM仍按继承链决议,接口默认方法根本不会被触发。