在 Java 编程中,方法重写(Method Overriding)是面向对象编程的一个核心概念,它允许子类通过重新实现父类的方法,来定制化行为,从而实现灵活的多态性!😎 你是不是也常常被“为什么需要方法重写?”“如何实现方法重写?”这些问题困扰呢?别担心,今天我们就通过一个实际案例,带你一起深入剖析方法重写的奥秘,助你成为 Java 编程高手!🚀
在这篇文章中,你将收获:
🌟 方法重写的基本概念与实际应用
🛠 如何在子类中重写父类的方法,并应用于实际问题
📚 方法重写的规则,以及常见问题解答如果你觉得这篇文章对你有帮助,记得给个大大的👍,让更多的小伙伴一起学习!🎉 别忘了收藏🔖,方便随时回顾,分享给更多正在学习 Java 的朋友们吧!💬 有问题或想法?欢迎在评论区留言,我们一起讨论,共同进步!💪🚀 还有,快点击关注🔔,获取更多编程干货和技术文章,绝对让你收获满满!📈
快开始阅读吧!👇
一.方法重写的案例
如果子类具有与父类相同的方法,则称为方法重写;换句话说,如果子类为其父类中的某个方法提供了特定的实现,则称为方法重写。
🚀 "让我们从一个实际的例子开始:"
在一个小型组织中,有两种员工:经理(Manager)和开发人员(Developer)。
现在我们需要打印员工的薪资。
创建 Employee.java
类
public class Employee {
int employeeId; // 员工的 ID
String employeeName; // 员工的姓名
double salary; // 员工的薪资
// 构造函数,用于初始化员工的 ID、姓名和薪资
public Employee(int employeeId, String employeeName, double salary) {
super(); // 调用父类的构造函数
this.employeeId = employeeId;
this.employeeName = employeeName;
this.salary = salary;
}
// 获取员工的 ID
public int getEmployeeId() {
return employeeId;
}
// 设置员工的 ID
public void setEmployeeId(int employeeId) {
this.employeeId = employeeId;
}
// 获取员工的姓名
public String getEmployeeName() {
return employeeName;
}
// 设置员工的姓名
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
// 获取员工的薪资
public double getSalary() {
return salary;
}
// 设置员工的薪资
public void setSalary(double salary) {
this.salary = salary;
}
}
创建 Manager.java
类
public class Manager extends Employee {
// 经理的奖金百分比
public static final double BONUSPERCENT = 0.2;
// 构造函数,初始化经理的 ID、姓名和薪资
public Manager(int employeeId, String employeeName, double salary) {
super(employeeId, employeeName, salary); // 调用父类构造函数
}
// 重写 getSalary() 方法,计算并返回经理的薪资(包括奖金)
@Override
public double getSalary() {
return salary + salary * BONUSPERCENT; // 返回薪资加上奖金
}
}
创建 Developer.java
类
public class Developer extends Employee {
// 开发人员的奖金百分比
public static final double BONUSPERCENT = 0.1;
// 构造函数,初始化开发人员的 ID、姓名和薪资
public Developer(int employeeId, String employeeName, double salary) {
super(employeeId, employeeName, salary); // 调用父类构造函数
}
// 重写 getSalary() 方法,计算并返回开发人员的薪资(包括奖金)
@Override
public double getSalary() {
return salary + salary * BONUSPERCENT; // 返回薪资加上奖金
}
}
创建 MethodOverridingMain.java
类
public class MethodOverridingMain {
/**
* 主程序入口
*/
public static void main(String[] args) {
// 创建开发人员对象 d1 和 d2
Developer d1 = new Developer(1, "Arpit", 20000);
Developer d2 = new Developer(2, "John", 15000);
// 创建经理对象 m1 和 m2
Manager m1 = new Manager(1, "Amit", 30000);
Manager m2 = new Manager(2, "Ashwin", 50000);
// 输出每个员工的姓名和薪资
System.out.println("Name of Employee: " + d1.getEmployeeName() + "---" + "Salary: " + d1.getSalary());
System.out.println("Name of Employee: " + d2.getEmployeeName() + "---" + "Salary: " + d2.getSalary());
System.out.println("Name of Employee: " + m1.getEmployeeName() + "---" + "Salary: " + m1.getSalary());
System.out.println("Name of Employee: " + m2.getEmployeeName() + "---" + "Salary: " + m2.getSalary());
}
}
当你运行 MethodOverridingMain.java
时,输出将是:
Name of Employee: Arpit—Salary: 22000.0
Name of Employee: John—Salary: 16500.0
Name of Employee: Amit—Salary: 36000.0
Name of Employee: Ashwin—Salary: 60000.0
如你所见,我们在 Developer
和 Manager
类中重写了 Employee
类的 getSalary()
方法。为什么我们需要重写 getSalary()
方法?
因为我们需要根据不同的类实现不同的 getSalary()
方法。例如,Developer
类和 Manager
类的奖金不同,因此我们需要为两者提供不同的实现。
二.方法重写的规则
- 参数:不能更改
- 返回类型:除了协变返回类型(子类型返回类型)外,不能更改
- 访问修饰符:不能更严格,可以更宽松
- 异常:可以减少或消除,但不能抛出新的或更广泛的已检查异常
- 构造方法:不能重写
- 静态方法:不能重写
- final 方法:不能重写
三.常见问题解答
为什么不能将访问修饰符设为更严格(如将 public 改为 private)?
这是面向对象编程中的基本原则:子类是父类的一个完全实例,因此必须至少具有与父类相同的接口。将访问修饰符设为更严格会违反这个原则,因为即使是子类的实例,也应该可以作为父类的实例使用。
示例代码:
class Employee {
public double getSalary() {
// 一些操作
}
}
class Developer extends Employee {
private double getSalary() {
// 一些操作
}
}
public class Main {
public static void main(String[] args) {
Employee e1 = new Developer();
e1.getSalary(); // 即使你把 Developer 的 getSalary() 方法设置为 private,仍然能访问
}
}
为什么不能重写静态方法?
静态方法与类相关,而不是与对象的状态相关。因此,你可以在子类中声明静态方法,但它与父类没有关系。它属于方法隐藏,而不是方法重写。
可以重写私有方法吗?
不可以,私有方法无法被重写,因为它在其他类中不可见。你可以在子类中声明一个新的方法,但它与父类的方法无关,所以这不是方法重写。
为什么不能重写 final
方法?
因为 final
方法是为了防止在子类中被重写。声明方法为 final
是因为你不希望它在子类中被修改。
如果我们改变参数的数量呢?
如果改变参数的数量,那就是方法重载,而不是方法重写。父类方法和子类方法必须具有相同的方法签名。
什么是动态绑定?
动态绑定是指在运行时绑定重写的方法。这意味着在编译时无法确定哪个方法会被调用,而是在程序运行时决定。
四.super
关键字的使用
super
关键字用于从子类调用特定的父类方法。
看如下代码示例:
// 定义一个名为 Employee 的类
public class Employee {
// 定义一个返回员工薪水的 getSalary() 方法
public double getSalary(){
// 输出信息,说明当前调用的是 Employee 类的 getSalary() 方法
System.out.println("In Employee class getSalary() method");
// 返回一个默认的薪资值,这里为 0
return 0;
}
// 主方法,程序入口
public static void main(String args[]) {
// 创建一个 Developer 类型的对象 d1,这个对象是 Employee 的子类
Developer d1 = new Developer();
// 调用 Developer 对象 d1 的 getSalary() 方法
d1.getSalary(); // 这里将会调用 Developer 类中的重写方法
}
}
// 定义一个名为 Developer 的类,它继承自 Employee 类
class Developer extends Employee {
// 重写 Employee 类中的 getSalary() 方法
public double getSalary(){
// 调用父类 Employee 的 getSalary() 方法
super.getSalary(); // super 关键字用于调用父类的方法
// 输出信息,说明当前调用的是 Developer 类的 getSalary() 方法
System.out.println("In Developer class getSalary() method");
// 返回一个默认的薪资值,这里为 0
return 0;
}
}
当你运行上述代码,会得到如下输入结果:
In Employee class getSalary() method
In Developer class getSalary() method
通过这篇文章的分享,你已经掌握了方法重写的基本概念和实际应用技巧!🎉 你会发现,方法重写不仅是 Java 编程中不可或缺的技术,它也是实现灵活多态、增强代码复用性和可扩展性的重要利器!🔧 现在你可以轻松应对各种面向对象编程的挑战,并在实际开发中灵活运用。
但这只是 Java 编程世界中的一个小小入口🚪,如果你对面向对象编程、继承、接口等高级概念感兴趣,别忘了继续关注我的文章!📚 我将继续为大家带来更多深入的技术干货,让你在编程路上越走越远,成为更强的开发者!💪
如果你觉得这篇文章对你有所帮助,记得给个大大的👍,点赞和收藏都是我继续创作的动力!💥 你可以将这篇文章分享给需要的朋友,帮助更多人走上学习编程的道路!🚀
如果你有任何问题或者对方法重写有更深入的理解,欢迎在评论区留言📝,我们一起讨论、一起进步!记得点击关注🔔,获取更多技术文章和编程资源,让我们一起成为更强的 Java 开发者!🚀🔥
保持学习,保持进步,我们下次见!👋📚