1. 继承1.1 定义和语法让一个类子类 / 派生类获取另一个类父类 / 基类 / 超类的属性和方法相同的属性和方法不需要再次定义子类只中只需要声明自己独特的属性和方法。语法// 父类定义 class 父类名 { // 共性属性和方法 } // 子类继承父类 class 子类名 extends 父类名 { // 子类独有属性和方法 }1.2 继承的访问规则1.3 继承的使用细节1. 子类会继承父类的全部成员包括private但private成员在子类中不能直接访问必须通过父类提供的public/protected方法如 getter/setter间接操作。2. 创建子类对象时必须先初始化父类部分因此子类构造器必须调用父类构造器默认隐式调用super()。3. 默认调用父类无参构造器父类无无参构造器时子类必须显式用super指定4.显式调用父类指定构造器super(参数列表)class Father { // 父类只有有参构造器无无参构造器 public Father(String name) { System.out.println(父类有参构造器 name); } } class Son extends Father { public Son() { // ❌ 编译报错父类没有无参构造器必须显式调用super(参数) // 正确写法 super(父亲); // ✅ 必须放在首行指定调用父类有参构造器 System.out.println(子类构造器执行); } }5.super必须放在构造器第一行且仅能在构造器中使用6.super()和this()不能共存于一个构造器7. Java 所有类都是Object的子类java.lang.Object是 Java 的顶级父类任何类包括自定义类、数组、集合都直接或间接继承Object因此都拥有equals()、toString()、hashCode()等方法。8. 一个子类只能有一个直接父类但可以通过多层继承间接继承多个父类如 A→B→CA 间接继承 B 和 C。9. 继承不能滥用必须符合 “子类是父类的一种” 的语义比如Dog is a Animal合理Dog extends Book就不合理。1.4 继承的内存布局class GrandPa { String name 大头爷爷; String hobby 旅游; } class Father extends GrandPa { String name 大头爸爸; int age 39; } class Son extends Father { String name 大头儿子; public void showNames() { System.out.println(Sons name: this.name); // 大头儿子 System.out.println(Fathers name: super.name); // 大头爸爸 // 访问更上层GrandPa的name需要在Father中提供方法 } } public class ExtendsTheory { public static void main(String[] args) { Son son new Son(); son.showNames(); // 输出 // Sons name: 大头儿子 // Fathers name: 大头爸爸 } }栈 (main方法) ┌───────────────────────────┐ │ son 0X11 (堆中Son对象地址) │ └───────────────────────────┘ ↓ 引用指向 堆 (Son对象 0X11) ┌───────────────────────────┐ │ GrandPa区域 │ │ name → 0X22 │ │ hobby → 0X33 │ ├───────────────────────────┤ │ Father区域 │ │ name → 0X44 │ │ age 39 │ ├───────────────────────────┤ │ Son区域 │ │ name → 0X55 │ └───────────────────────────┘ ↓ 字符串引用指向 方法区 (常量池) ┌───────────────────────────┐ │ 大头爷爷 → 0X22 │ │ 旅游 → 0X33 │ │ 大头爸爸 → 0X44 │ │ 大头儿子 → 0X55 │ └───────────────────────────┘ 方法区 (类继承链) ┌───────────────────────────┐ │ Object ← GrandPa ← Father ← Son │ └───────────────────────────┘当执行Son son new Son();时JVM 首先在方法区加载GrandPa、Father、Son的类信息并构建继承链Object ← GrandPa ← Father ← Son同时将 大头爷爷 大头爸爸 等字符串常量存入方法区的常量池接着在堆内存中创建地址为0X11的Son对象实例该对象按继承层级分为三层独立区域 —— 最上层是GrandPa区域存储name指向常量池0X22、hobby指向0X33中间层是Father区域存储name指向0X44、age直接存值 39最下层是Son区域存储name指向0X55三层区域完整包含所有父类和子类的属性且同名属性互不覆盖最后在栈内存的main方法栈帧中创建引用变量son存储堆中Son对象的地址0X11当通过son.name或super.name访问属性时JVM 会根据this/super关键字定位到堆中对应层级的属性区域再通过区域内的地址指向方法区常量池获取具体字符串值。2. super关键字2.1 用法用法作用注意事项super.属性名访问父类的属性尤其子类有同名属性时不能访问父类private属性super.方法名(参数)调用父类的方法尤其子类重写了父类方法时不能调用父类private方法super(参数)调用父类的构造器必须放在子类构造器的首行无参时默认调用super()不能和this()共存2.2 使用细节1. 当子类和父类存在同名属性或方法时默认访问的是子类自己的成员如果要访问父类的同名成员必须使用super.成员名来明确指定。如果成员没有重名那么super.成员名、this.成员名、直接写成员名这三种写法效果完全一致都会向上查找到可用的成员。class Father { String name 大头爸爸; int age 39; public void sayHello() { System.out.println(父类你好); } } class Son extends Father { // 与父类同名的属性 String name 大头儿子; // 与父类同名的方法 Override public void sayHello() { System.out.println(子类哈喽); } public void testAccess() { // 1. 同名成员必须用super访问父类 System.out.println(this.name); // 输出大头儿子默认访问子类 System.out.println(super.name); // 输出大头爸爸访问父类 this.sayHello(); // 输出子类哈喽 super.sayHello(); // 输出父类你好 // 2. 无重名成员三种写法效果一样 System.out.println(age); // 输出39 System.out.println(this.age); // 输出39 System.out.println(super.age); // 输出39 } } public class Test { public static void main(String[] args) { Son son new Son(); son.testAccess(); } }2.super不仅可以访问直接父类还能访问更上层的父类比如爷爷类从当前类的直接父类开始向上查找找到第一个同名且可访问的成员就使用它否则报错2.3 super 和 this 的比较