方法的重写(override/overwrite)
- 重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作
- 应用:重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数方法时,实际执行的是子类重写父类的方法。
重写的规定:
方法的声明:权限修饰符 返回值类型 方法名(形参列表) throw 异常类型{
方法体
}
约定俗称:子类中的叫重写的方法,父类中的叫做被重写方法
① 子类重写的方法的方法名和形参列表与父类被重写的方法名和形参列表相同
② 子类重写的权限修饰符不小于被重写的方法的权限修饰符
特殊情况:子类不能重写父类中声明为private权限的方法,此时不能称为重写
③ 返回值类型:
-
父类被重写的方法的返回值类型是void,则子类重写的返回值类型只能是void
-
父类被重写的方法的返回值类型是A类型,则子类重写的方法的返回值类型可以是A类或A类的子类
-
父类被重写的方法的返回值类型为基本数据类型(比如:double),则子类重写的方法的返回值类型必须是相同的基本数据类型(必须也是:double)
④ 子类重写的方法抛出的异常类型不大于父类被重写的方法抛出的异常类型
子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写)。
-
若子类重写了父类方法,就意味着走子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。编译看左边,运行看右边
-
对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量。这个实例变量依然不可能覆盖父类中定义的实例变量
子类和父类中的同名同参数的方法要么都声明为非static的(考虑重写),要么都声明为static的(不是重写)。
面试题:请你说说重载与重写的区别,构造方法能不能重写?
重载要求发生在同一个类中,多个方法之间方法名相同且参数列表不同。重载与方法的返回值以及访问修饰符无关。重写发生在父类子类中,若子类方法想要和父类方法构成重写关系,则它的方法名、参数列表必须与父类方法相同。
另外,返回值要小于等于父类方法,抛出的异常要小于等于父类方法,访问修饰符则要大于等于父类方法。若父类方法的访问修饰符为private,则子类不能对其重写。其实除了二者都发生在方法之间,要求方法名相同之外并没有太大相同点。
同一个类中有多个构造器,多个构造器的形参列表不同就被称为构造器重载,构造器重载让Java类包含了多个初始化逻辑,从而允许使用不同的构造器来初始化对象。构造方法不能重写。因为构造方法需要和类保持同名,而重写的要求是子类方法要和父类方法保持同名。如果允许重写构造方法的话,那么子类中将会存在与类名不同的构造方法,这与构造方法的要求是矛盾的。父类方法和子类方法之间也有可能发生重载,因为子类会获得父类的方法,如果子类中定义了一个与父类方法名字相同但参数列表不同的方法,就会形成子类方法和父类方法的重载。
Person.java
public class Person {
private String name;
private int age;
private boolean isMale;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isMale() {
return isMale;
}
public void setMale(boolean male) {
isMale = male;
}
public Person() {
}
public Person(String name, int age, boolean isMale) {
this.name = name;
this.age = age;
this.isMale = isMale;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void walk(double distance){
System.out.println("行走"+distance+"公里");
}
public void eat(){
System.out.println("吃饭ing");
}
public void sleep(double hour){
System.out.println("休息"+hour+"小时");
}
}
Student.java
public class Student extends Person{
private String major;
public Student(){
}
public String getMajor() {
return major;
}
public void setMajor(String major) {
this.major = major;
}
public Student(String major){
this.major = major;
}
public void study(){
System.out.println("学习的专业是:"+this.major);
}
@Override
public void eat() {
System.out.println("学生应该均衡营养");
//super.eat();
}
}
PersonTest.java
public class PersonTest {
public static void main(String[] args) {
Student student = new Student("计算机科学与技术");
student.eat();
}
}