Java基础之(八)方法覆盖

子类从父类中继承方法,有时子类需要修改父类中定义的方法的实现,这称作方法覆盖。比如下面这个例子:

class Person {
    String  name;
    int age;

    void introduce(){
        System.out.println("我的姓名是:" + name+",我的年龄是"+ age);
    }

}
class Student extends Person {

    String address;

    void introduce(){
        System.out.println("我的姓名是"+ name + ",我的年龄是"+ age);
        System.out.println("我的家在"+ address);
    }   
}
class Test{
public static void main(String args[]){
    Student s = new Student();
    s.name = "张三";
    s.age = 20;
    s.address = "北京";   
    s.introduce();
    }
}

introduce()方法在Person类中定义,在Student类中修改。并且这两个方法定义(返回值类型、方法名、参数列表)相同,只不过方法体不一样,这样的两个方法的关系我们称之为方法覆盖,有的书上也称之为方法重写/复写。

1.语法特征

  1. 在具有父子关系的两个类中
  2. 父类和子类中各有一个函数,这两个函数的定义完全相同
输出结果:
我的姓名是张三,我的年龄是20
我的家在北京

2.super调用成员方法

在上面的代码中我们能够发现重复代码:

System.out.println("我的姓名是"+ name + ",我的年龄是"+ age);

怎么解决这个问题,这时候可以用super关键字:

void introduce(){
        super.introduce();
        System.out.println("我的家在"+ address);
    }   
}

3.覆盖的注意事项

  • 仅当方法是可访问时,它才能被覆盖。这样,因为私有方法在它的类本身以外是不能访问的,所以它不能被覆盖。如果子类中定义的方法在父类中是私有的,那么这两个方法完全没有关系。比如:
public class Person {

public void introduce() {…}

}

public class Student extends Person {

private void introduce() {…} //编译错误,子类方法缩小了父类方法的访问权限

}
  • 与实例方法一样,静态方法也能被继承。但是,静态方法不能被覆盖。如果父类中定义的静态方法在子类中被重新定义,那么定义在父类中的静态方法将被隐藏。可以使用语法:父类名.静态方法名调用隐藏的静态方法。比如:
public class Person {

public static void introduce() { }

}

public class Student extends Person {

public void introduce() { } //编译出错

}

Super调用成员变量

如果子类定义了和父类同名的成员变量,则会发生子类变量隐藏父类变量的情形。在正常情况下,子类中定义的方法直接访问该变量默认会访问到子类中定义的变量,无法访问到父类中被隐藏的变量。
在子类定义的实例方法中可以通过super来调用父类中被隐藏的变量,如下代码所示:

class BaseClass{
    public int a = 5;
}

public class SubClass extends BaseClass{
    public int a = 7;

    public void accessOwner(){
        System.out.println(a);
    }

    public void accessBase(){
        //通过super来限定访问从父类继承得到的a变量
        System.out.println(super.a);
    }

    public static void main(String[] args){
        SubClass sc = new SubClass();
        //输出7
        sc.accessOwner();
        //输出5
        sc.accessBase();
    }
}