Java中的方法重写(非常详细,附带实例)
在 Java 的继承机制中,当父类中的方法无法满足子类需求或子类具有特有的功能时,就需要在子类中重写父类的方法(也称为方法覆盖)。
准确地说,方法重写建立在继承关系之上,具体是指子类从父类中继承方法时,如果在子类中有方法名和参数列表均与父类中的方法完全一致,但方法内容不同的方法,即子类修改了父类中方法的实现,此时创建的子类对象调用这个方法时,程序会调用子类的方法来执行,即子类的方法重写了从父类继承过来的同名方法。
当子类重写父类方法时,可以使用与父类相同的方法名及参数列表,也可以执行不同的功能。子类既可以隐藏和访问父类的方法,也可以覆盖父类的方法。
接下来,通过案例来演示方法重写。以 Animal 为父类,Dog 类、Cat 类继承 Animal 类,Dog 类重写了父类的 show() 方法。
从程序运行结果中可发现,第 30 行代码直接调用 Dog() 构造方法,理应输出“调用了狗类的构造方法Dog()”,但是先输出“调用了动物类的构造方法Animal()”,这是因为在执行子类的构造方法前,会首先调用父类中无参的构造方法,其目的是为了对继承自父类的成员进行初始化操作。
第 34 行代码在调用 Dog 类对象的 show() 方法时,只会调用子类重写的方法,并不会调用父类的 show() 方法。
Cat 类中没有重写父类的 show() 方法,第 37 行代码中的 Cat 类对象仍然调用的是父类的 show() 方法,同时由于没有给 Cat 类对象的成员变量 name 和 age 赋值,所以显示的名字是默认值“null”,年龄也是默认值“0”。
方法重写时必须注意如下事项:
准确地说,方法重写建立在继承关系之上,具体是指子类从父类中继承方法时,如果在子类中有方法名和参数列表均与父类中的方法完全一致,但方法内容不同的方法,即子类修改了父类中方法的实现,此时创建的子类对象调用这个方法时,程序会调用子类的方法来执行,即子类的方法重写了从父类继承过来的同名方法。
当子类重写父类方法时,可以使用与父类相同的方法名及参数列表,也可以执行不同的功能。子类既可以隐藏和访问父类的方法,也可以覆盖父类的方法。
接下来,通过案例来演示方法重写。以 Animal 为父类,Dog 类、Cat 类继承 Animal 类,Dog 类重写了父类的 show() 方法。
class Animal { // 定义父类Animal类 public String name; public int age; public Animal() { System.out.println("调用了动物类的构造方法Animal()"); } public void show() { System.out.println("父类名字是" + name + ", 年龄: " + age); } } class Dog extends Animal { // 定义子类Dog类 String color; public Dog() { System.out.println("调用了狗类的构造方法Dog()"); } public void eat() { System.out.println(color + "的狗狗在啃骨头"); } public void show() { System.out.println("狗狗名字是" + name + ", 颜色是" + color); } } class Cat extends Animal { // 定义子类Cat类 } public class Demo { public static void main(String[] args) { Dog d = new Dog(); d.name = "旺财"; d.age = 2; d.color = "黑色"; d.show(); d.eat(); Cat c = new Cat(); c.show(); } }程序的运行结果如下:
调用了动物类的构造方法Animal()
调用了狗类的构造方法Dog()
狗狗名字是旺财,颜色是黑色
黑色的狗狗在啃骨头
调用了动物类的构造方法Animal()
父类名字是null,年龄:0
从程序运行结果中可发现,第 30 行代码直接调用 Dog() 构造方法,理应输出“调用了狗类的构造方法Dog()”,但是先输出“调用了动物类的构造方法Animal()”,这是因为在执行子类的构造方法前,会首先调用父类中无参的构造方法,其目的是为了对继承自父类的成员进行初始化操作。
第 34 行代码在调用 Dog 类对象的 show() 方法时,只会调用子类重写的方法,并不会调用父类的 show() 方法。
Cat 类中没有重写父类的 show() 方法,第 37 行代码中的 Cat 类对象仍然调用的是父类的 show() 方法,同时由于没有给 Cat 类对象的成员变量 name 和 age 赋值,所以显示的名字是默认值“null”,年龄也是默认值“0”。
方法重写时必须注意如下事项:
- 构造方法不能被继承,不能被重写;
- 必须考虑权限,即被子类重写的方法不能拥有比父类方法更加严格的访问权限;
- 重写方法所抛出的异常不能比原方法更多,如果抛出比父类方法更多的异常,则在编译时会报错。
Java方法重写和方法重载的区别
前面已经讲过方法重载,下表罗列了方法重载与方法重写的主要区别。方法重载 | 方法重写 |
---|---|
参数类型、参数个数、参数类型的顺序不同 | 参数个数、参数类型、参数类型的顺序完全相同 |
返回值类型可以相同,可以不相同 | 返回值类型完全相同 |
访问权限修饰符可相同,可不同 | 子类重写父类方法时,修饰符权限要大于等于父类修饰符权限,父类被 private 修饰的方法不能被重写 |