← 返回首页
JavaSE系列教程 (二十六)
发表时间:2020-01-03 15:37:44
讲解什么是属性覆盖和super关键字。

1.子类构造方法中必须调用父类构造方法

因为有继承关系存在时子类需要把父类的属性继承下来。所以在执行子类的构造方法的过程中,必须先调用其父类的构造方法。

看如下代码:

public class Father {

    protected String firstName = "张";

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    Father(){

        System.out.println("Father Constructor is run...");
    }
}

public class Son extends Father {

    Son(){
         //super(); //这里隐含着去调用了父类默认无参数的构造方法。
         System.out.println("Son Constructor is run...");
    }

}

public class Test {
    public static void main(String[] args) {

        Son s = new Son();

        System.out.println(s.getFirstName());
    }
}

运行结果:
Father Constructor is run...
Son Constructor is run...
张

结论:执行子类子类构造方法时,第一句话总是默认先去调用父类无参数的构造方法,如果父类没有默认无参数的构造方法,则需要显示调用父类带参数的构造方法,以完成父类属性的初始化。

2.属性覆盖

我们知道子类重写从父类继承过来的方法称为方法重写,那么子类是不能重写从父类继承过来的属性,但是子类可以覆盖父类的属性。

例如以下代码:

public class Father {

    protected String firstName = "张";

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    Father(){

        System.out.println("Father Constructor is run...");
    }
}

public class Son extends Father {

    String firstName = "李"; //这里出现了属性覆盖。

    @Override
    public String getFirstName() {
        return firstName;
    }

    @Override
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    Son(){
         //super(); //这里隐含着去调用了父类默认无参数的构造方法。
         System.out.println("Son Constructor is run...");
    }

}

public class Test {
    public static void main(String[] args) {

        Son s = new Son();

        System.out.println(s.getFirstName());
    }
}

运行结果:
Father Constructor is run...
Son Constructor is run...
李

3.super关键字

在Java中super有两种使用场景。1.调用父类的构造方法。2.调用父类的属性和方法。

1)调用父类的构造方法。

public class Father {

    protected String firstName ;

    Father(String firstName){
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

}

public class Son extends Father {

    String firstName = "李";

    @Override
    public String getFirstName() {
        return firstName;
    }

    @Override
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }


    public Son(String firstName,String changeName) {
        super(firstName);//显式调用父类带参数的构造方法
        this.firstName = changeName;
    }

}

public class Test {
    public static void main(String[] args) {

        Son s = new Son("张","李");

        System.out.println(s.getFirstName());

    }
}

运行结果:
李

2)调用父类的属性和成员方法

public class Father {

    protected String firstName ;

    Father(String firstName){
        this.firstName = firstName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void fn(){
        System.out.println("我是Father fn()...");
    }

}

public class Son extends Father {

    String firstName = "李";

    @Override
    public String getFirstName() {
        return firstName;
    }

    @Override
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }


    public Son(String firstName,String changeName) {
        super(firstName);//显式调用父类带参数的构造方法
        this.firstName = changeName;
    }


    @Override
    public void fn() {
        super.fn(); //调用父类的成员方法
        System.out.println("Father fisrtName:"+super.firstName); //调用父类的属性
        System.out.println("Son fisrtName:"+this.firstName);
    }

}

public class Test {
    public static void main(String[] args) {

        Son s = new Son("张","李");

        s.fn();

    }
}
运行结果:

我是Father fn()...
Father fisrtName:张
Son fisrtName:李

小结:

1)子类的构造方法中必须调用父类的构造方法。

2)子类可以覆盖从父类继承过来的属性,覆盖后this.xxx获得的是覆盖后的属性,super.xxx覆盖之前父类的属性。

3)在Java中super有两种使用场景。1.调用父类的构造方法。2.调用父类的属性和方法。

4)通常情况下,在构造方法中this和super不能同时出现。(感兴趣的亲们,可以自己亲测!)