JAVA继承详细总结
看前摇一摇这篇文章:java 继承 补充:子类能继承父类中的哪些内容? - 小澳子 - 博客园
构造方法的继承规则
Java 中构造方法不会被子类继承。JLS 明确指出“构造方法不是类的成员,因此永远不会被继承”docs.oracle.com。博客原文在“继承内存图”及“构造方法的继承”小节中也指出:“构造方法无论是否私有都不能继承”cnblogs.com。同时,子类的构造方法会自动调用父类的构造方法:如果没有在子类构造器首行显式写 super(...)
,编译器会自动插入对父类无参构造的调用docs.oracle.comdocs.oracle.com。例如,如果父类只有带参构造而无无参构造,子类默认调用 super()
时会报错cnblogs.comdocs.oracle.com。博客最后“构造方法的访问特点”小节也提到:子类的所有构造方法默认先访问父类无参构造,再执行自身构造cnblogs.com。综上,构造方法不被继承,子类构造器必须通过 super
调用父类构造器(或者编译器自动插入),以确保父类对象空间先完成初始化docs.oracle.comdocs.oracle.com。
成员变量的继承与访问
父类的成员变量会随继承进入子类对象的内存空间:在创建对象时,JVM 会为父类和子类分别分配字段存储区cnblogs.com。不过,访问权限决定了子类能否使用这些字段:根据 JLS,“声明为 private
的类成员不被继承”docs.oracle.com。博客中也指出,被 private
修饰的成员变量虽然在内存中存在,但不能被直接访问cnblogs.com。此外,如果子类定义了与父类同名的字段,就会发生字段遮蔽:未加修饰访问时遵循就近原则(先查找局部变量,再查找子类字段,最后查找父类字段)cnblogs.com;使用 this.
强制访问子类字段,使用 super.
则访问父类字段cnblogs.com。官方教程也指出,子类中与父类同名的字段会隐藏父类字段,想访问父类字段需要通过 super
docs.oracle.com。
父类私有的成员变量子类也可以继承,但是只能通过get()和set()方法进行访问和操作:
成员方法的继承与虚方法
子类会继承父类的非私有方法:JLS 规定只有 protected
或 public
的成员才被继承docs.oracle.com。博客中提到,JVM 从最顶层父类开始为所有非 private、非 static、非 final的实例方法建立“虚方法表”(Virtual Method Table),并逐级加入虚方法cnblogs.com。这些方法即为 Java 的虚方法:它们可以被子类重写,运行时根据对象实际类型进行调用。官方教程将这种行为称为 “虚方法调用”:JVM 根据对象类型调用相应方法,而不是根据引用变量的类型docs.oracle.com。因此,“虚方法”在 Java 中本质上指可被覆盖的实例方法。只有加入虚方法表的方法才被子类继承cnblogs.com,这与 JLS 的继承规则是一致的:private
方法既不在虚方法表中,也不被继承docs.oracle.comcnblogs.com。也就是说,Java 中非私有实例方法既是继承的对象也是虚方法,两者并无矛盾。
变量遮蔽(字段隐藏)
如果子类声明了与父类同名的字段,就会产生遮蔽效果。通过“就近原则”描述了访问过程:若字段名相同,默认不加修饰时会优先查找当前方法的局部变量,然后是子类的字段,最后才是父类的字段;使用 this.field
强调访问子类字段,使用 super.field
强调访问父类字段cnblogs.com。Oracle 官方教程也说明:子类同名字段会隐藏父类字段,要访问父类的字段只能通过 super
docs.oracle.com。例如博客给出的示例中,输出 name
、this.name
、super.name
时分别对应当前方法局部、子类字段和父类字段的值cnblogs.com。
方法重写(Override)
子类可以重写父类的方法以改变行为。重写要求方法签名保持一致:方法名和参数列表必须与父类完全相同docs.oracle.comcnblogs.com;返回类型可以是父类返回类型的子类型(协变返回)docs.oracle.com。重写方法的访问权限不得低于被重写方法cnblogs.com;建议使用 @Override
注解帮助编译器检查重写是否正确cnblogs.com。只有那些继承下来的方法(即非私有实例方法)才有可能被重写cnblogs.comdocs.oracle.com。官方教程总结:子类中具有与父类方法相同签名的实例方法会覆盖(override)父类的方法docs.oracle.com。例如若父类有 public void foo()
,则子类重写时也应声明为 public void foo()
(不能是 private
或返回类型不匹配)cnblogs.com。
虚方法与非私有成员继承的关系
java 中虚方法即是可被继承和覆盖的方法(所有非 private
、非 static
、非 final
的实例方法)cnblogs.comdocs.oracle.com。JLS 规定私有方法不继承docs.oracle.com,而这些私有方法也不属于虚方法表。