【Java面向对象】5-3 方法重写

§5-3 方法重写

类的继承关系使得子类能够继承父类的方法。本节将主要讨论方法重写。

5-3.1 方法重写

方法重载是指在同一类中方法名和方法的返回值相同情况下,构造形参列表不同的方法。与方法重载不同,方法重写是在具有继承关系的类中,方法返回值类型、方法名、形参列表都相同的情况下,对某一类中的方法的重构。一个最明显的区别是,重载在同一类中发生,而重写发生在具有继承关系的不同类之中,且重写的方法访问权限相同

5-3.1.1 静态方法重写

首先我们先看看静态方法重写。

//Root.java
public class Root {
    public static void test() {
        System.out.println("执行Root --> test()");
    }
}

//Branch.java
public class Branch extends Root {
    public static void test() {
        System.out.println("执行Branch --> test()");
    }
}

在主方法中调用:

//Application.java
public class Application {
    public static void main(String[] args) {
        //静态方法重写
        Branch branch = new Branch();
        branch.test();  //新建子类对象,并调用其静态方法。
        Root root = new Branch();   //在父类新建子类对象,父类引用指向子类对象,子类继承,向上传递
        root.test();
    }
}

编译后运行,得到结果:

执行Branch --> test()
执行Root --> test()

可见,若都为静态方法,则无论创建对象时调用的是谁的构造器(创建谁的对象),重写后调用时只与所属类有关。这在一定程度上说明,静态方法是随着类加载的是类的方法

这样看来,方法重写对于静态方法而言没有意义,因为静态方法随着类一同载入方法区中。因此,我们讨论的方法重写都是针对于非静态方法。

5-3.1.2 非静态方法重写

倘若我们把上述方法都改为非静态方法:

//Root.java
public class Root {
    public void test() {
        System.out.println("执行Root --> test()");
    }
}

//Branch.java
public class Branch extends Root {
    @Override	//注解(带有功能)
    public void test() {
        System.out.println("执行Branch --> test()");
    }
}

再次编译运行,则得到结果:

执行Branch --> test()
执行Branch --> test()

可见,这时都调用了子类的方法。这也说明,非静态方法存在于对象中是对象的方法。调用方法时,和对象有关。为了方法的可用性在外部使用),方法的重写针对的是public 修饰的方法

IDEA 快捷键:按下组合键 Alt + Insert ,选择 重写方法(Override)

5-3.1.3 注意点

有关方法的重写,需要明确的是:

  1. 重写发生在具有继承关系的类中,且必须是子类重写父类的方法
  2. 方法名、参数列表、返回值类型必须相同;
  3. 重写的方法修饰符范围可以扩大,但不可以缩小;
  4. 抛出的异常范围可以被缩小,但不可以扩大;
  5. final 修饰的方法不可以被重写;

那么,我们何时需要方法重写呢?

我们以[5-4 继承](5 - 4 继承.md)中的例子来看:

//Creature.java
public class Creature {
    String name = "生物";		//成员变量初始化
    
    public Creature() {
        System.out.println("已调用父类构造器。")
    }
    
    public String getName() {
        return name;		//若只进行了初始化,那么将默认输出:生物
    }
    
    public void setName(String newName) {
        this.name = newName;
    }
}

//Animal.java
public class Animal extends Creature {
    String name = "动物";
    
    public Animal() {
        super();			//super关键字,将在下文中提到
        System.out.println("已调用子类构造器。")
    }
    
    //子类缺省父类的 getName() 和 setName() 方法
}

若没有在子类中重写父类的 getName()setName() 方法,那么在主方法中无参创建子类的对象后,调用 getName() 方法,会发现并没有输出 动物,而是 生物。因此,当父类的方法子类不一定需要或子类所需条件父类不一定满足时往往需要方法重写

posted @ 2023-03-11 21:44  Zebt  阅读(46)  评论(0)    收藏  举报