返回首页

java继承,父类子类,super,重写,多态

1494 字 7 分钟
回顾#
this.score = score;
  • 左边 this.score:当前对象的成员属性。
  • 右边 score:构造方法或普通方法接收到的参数,不是对象属性。 如果写成:
score = score;

相当于参数给自己赋值,对象的成绩属性仍为默认值 0

static 表示成员属于类,所有对象共享一份;不代表所有位置都能访问,访问范围仍由 private/public 决定。

学习内容#
  • 继承 extends
  • 父类与子类
  • super
  • 方法重写
  • 多态 掌握:extendssuper、方法重写以及父类引用指向子类对象。 问题:重载与重写的区别、多态的实际执行方法、父子类构造顺序。
模块一:继承#

继承表示一个类可以在已有类的基础上继续扩展。 例如:

public class Account {
private String username = "admin";
public String getUsername() {
return username;
}
public void login() {
System.out.println(username + "登录系统");
}
}

管理员账户也是一种账户,因此可以继承 Account

public class AdminAccount extends Account {
public void manageUsers() {
System.out.println(getUsername() + "管理用户");
}
}

测试类:

public class InheritanceDemo {
public static void main(String[] args) {
AdminAccount admin = new AdminAccount();
admin.login();
admin.manageUsers();
System.out.println(admin.getUsername());
}
}

运行结果:

admin登录系统
admin管理用户
admin

这里 AdminAccount 自己只定义了 manageUsers(),但对象还能调用父类提供的 login()getUsername()

实际开发中可以表达:

AdminAccount 是一种 Account
JavaDeveloper 是一种 Employee
Dog 是一种 Animal

继承适合表达“子类是一种父类”的关系,也就是 is-a 关系。

常见错误:

  • 为了复用几行代码,强行建立没有 is-a 关系的继承。
  • 子类直接访问父类的 private 属性。
  • extends 理解成复制粘贴父类代码。
  • Java 类只能直接继承一个父类。
模块二:super#

父类中如果使用了构造方法 子类中需要使用super进行辅助初始化 形式:

super(name);

调用父类构造方法,必须位于子类构造方法的第一条有效语句。 为什么需要: 父类只有这个构造方法:

public Employee(String name) {
this.name = name;
}

没有无参数构造方法:

public Employee() {
}

如果子类构造方法不写 super(name),编译器会尝试自动添加:

super();

但是父类没有 Employee(),所以会编译失败。

super 调用父类普通方法#

super 不仅能调用父类构造方法,还能调用父类的方法:

@Override
public void work() {
super.work();
System.out.println(
getName() + "正在编写Java后端代码,技能:" + getSkill()
);
}

这里:

super.work();

明确调用父类 Employeework()

因此会依次输出:

员工正在工作
张三正在编写Java后端代码,技能:Spring Boot
  • super(name):调用父类构造方法。
  • super.work():调用父类普通方法。

方法重写 Override#

父类已经提供一个方法,但子类需要不同的实现时,可以重写这个方法。 父类:

public class Employee {
public void work() {
System.out.println("员工正在工作");
}
}

子类重写:

public class JavaDeveloper extends Employee {
@Override
public void work() {
System.out.println("Java开发人员正在编写代码");
}
}

调用:

JavaDeveloper developer = new JavaDeveloper(...);
developer.work();

执行的是子类重写后的 work()

@Override 是什么?#

它告诉编译器:

我准备重写父类的方法,请检查我的写法是否正确。

@Override
public void works() {
}

编译器会立即报错,防止你以为自己完成了重写。因此实际开发中,重写方法时应主动添加 @Override 只是帮助编译器检查,不决定一个方法是不是重写。即使把正确的 work() 上面的 @Override 删除,只要方法签名符合要求,它仍然是重写,只是失去了编译器的额外检查。

@Override

重写的基本要求#

子类方法需要与父类方法保持一致:

  • 方法名相同
  • 参数列表相同
  • 返回类型相同或符合兼容规则
  • 子类的访问权限不能比父类更严格 例如父类是 public,子类不能改成 private
为什么需要方法重写?#

不同员工都可以“工作”,但工作方式不同:

Employee:处理普通工作
JavaDeveloper:编写Java后端代码
Designer:设计页面

外部代码可以统一调用 work(),具体行为由不同子类决定。这会成为后面“多态”的基础。

模块四:多态#

Employee是父类,JavaDeveloper是子类 Employee employee = new JavaDeveloper("张三", "Spring Boot");

内容类型
employee 的声明类型Employee(父类)
实际创建的对象类型JavaDeveloper(子类)
创建的对象数量1个
两条核心规则#

第一条:编译时看左边。

编译器根据声明类型 Employee 判断可以调用哪些方法。因此只能直接调用 Employee 中已经声明的方法:

employee.getName(); // 可以
employee.clockIn(); // 可以
employee.work(); // 可以
employee.getSkill(); // 不可以

虽然实际对象中存在 getSkill(),但是 Employee 类型中没有这个方法,所以编译器不允许调用。

而且 skill 是子类的 private 属性,更不能直接访问。

第二条:运行时看右边。

EmployeeJavaDeveloper 都有 work(),而实际对象是 JavaDeveloper,所以:

employee.work();

运行的是子类重写后的版本。 可以记成:

能调用什么:看左边的声明类型
实际执行哪个重写方法:看右边的对象类型

如果确实需要直接使用子类特有的 getSkill(),目前可以声明为:

JavaDeveloper developer = new JavaDeveloper("张三", "Spring Boot"); developer.getSkill();

向下类型转换和安全判断会在后续结合 instanceof 学习。

问题: 假设 JavaDeveloper 重写了 work(),但没有重写 clockIn()

Employee employee =
new JavaDeveloper("李四", "MySQL");
employee.getName();
employee.clockIn();
employee.work();
employee.getSkill();

clockIn()执行父类还是子类版本? 执行父类Employee中的Kens clockIn()。 原因是 JavaDeveloper没有重写clockIn()`,它只是继承了父类现有的实现。实际对象是子类,不代表所有方法都会变成子类版本;只有被子类重写的方法才会执行子类版本。

clockIn():没有重写 → 使用父类实现
work():已经重写 → 使用子类实现
java继承,父类子类,super,重写,多态
https://335264.xyz/posts/java继承父类子类super重写多态/
作者
刺儿菜
发布于
2026-09-10
许可协议
CC BY-NC-SA 4.0
Comments

评论