彻底掌握 Java 方法重写:从实际案例到深入剖析,解决你所有疑问!

在 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

如你所见,我们在 DeveloperManager 类中重写了 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 开发者!🚀🔥

保持学习,保持进步,我们下次见!👋📚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大名顶顶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值