关于java中的super

Link-Soul / 2023-05-03 / 原文

首当其冲先说一下super的用途和含义。他是用于调用一些被重写的方法。

这里还可以复习一下子这个重写:重写是把新的方法放在被重写的方法前面。在被重写的子类中,优先调用重写后的方法。但是如果想要调用原本未被重写的方法的话,就需要super了。

如上的代码中ChildClass为FatherClass的子类。看得出来程序先运行super.f()之后是

class FatherClass{
    public int value;
    public void f(){
        value = 100;
        System.out.println("FatherClass:value="+value);
    }
}
class ChildClass extends FatherClass{


    @Override
    public void f() {       //方法在重写的时候并不会删除原方法,而是覆盖了。
                            //这样的就可以通过super去调用前面被覆盖的父类方法。
        super.f();          //调用父类的f
        value=200;
        System.out.println("ChildClass:value="+value);
        System.out.println("super.value="+super.value);//可以直接调用父类的
        super.f();
        System.out.println("ChildClass:value="+value);
    }

    public static void main(String[] args) {
//        ChildClass C = new ChildClass();//这玩意是用ChildClass类型赋值给C,
        //之后 new ChildClass是新的方法体
//        C.f();等价于
        new ChildClass().f();

    }
}

FatherClass:value=100
ChildClass:value=200
super.value=200
FatherClass:value=100
ChildClass:value=100

 

输出的结果也是如上。可以看得出子类在继承父类的变量时,是共用的。在value被赋值为200之后,
super.value也是200,执行super.f赋值后,子类中的value也变成了100



言归正传。super默认是调用父类的构造器。在子类的构造器中的第一行中,如果没有调用super的话,
那么在这一类中 java 就会默认调用super()。
public class TestSuper2 {
    public static void main(String[] args) {
        new ChildClass2();
    }

}
class FatherClass2{
    public FatherClass2(){
        System.out.println("调用父类构造器");
    }
}
class ChildClass2 extends FatherClass2{
    
}


调用父类构造器
如上的代码中,子类ChildClass2并没有任何内容,然而结果中还是调用了父类的构造器。证实了上面所说的


public class TestSuper2 {
    public static void main(String[] args) {
        new ChildClass2();
    }

}
class FatherClass2{
    public FatherClass2(){
        System.out.println("调用父类构造器");
    }
}
class ChildClass2 extends FatherClass2{

    public ChildClass2() {
    System.out.println("子类构造器");

    }
}

调用父类构造器

即便是有构造器,第一行没有写super() 仍然会调用构造方法。

 

那么调用一个父类的方法呢?

public class TestSuper2 {
    public static void main(String[] args) {
        new ChildClass2();
    }

}
class FatherClass2{
    public FatherClass2(){
        System.out.println("调用父类构造器");
    }
    void a(){
        System.out.println("调用a方法");
    }
}
class ChildClass2 extends FatherClass2{

    public ChildClass2() {
        super.a();
        System.out.println("子类构造器");
    }
}

调用父类构造器
调用a方法
子类构造器

 

答案是仍然会调用super()  (当然没有构造方法就不会调用的啦)

因此可以理解为在子类方法、构造器运行之前,会先去找父类的构造器。就如同Object类一样,

super()提供了一个为什么在运行普通类的时候,会先调用Object类的一个过程:

因为Object类是所有类的父类,有了super我们就能很好的解释Object是怎么在我们看不到的地方

被调用啦