面向对象 - super、方法重写Override

继续深入认识面向对象

狂神说Java BV12J41137hu

super

super 可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。

面向对象 - 内存分析、封装、继承 所写,继承的成员变量或者方法前缀修饰关键词必须是 publicprotected

引用父类成员变量及方法

Person.java

package oop.app.mysuper;

public class Person {
    protected String name = "PersonName";

    public Person() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    protected void printName() {
        System.out.println(this.name);
    }

}

Student.java

package oop.app.mysuper;

public class Student extends Person{
    public String name = "StudentName";

    public Student() {
    }

    public void printName() {
        System.out.println("name\t" + name);
        System.out.println("this.name\t" + this.name);
        System.out.println("super.name\t" + super.name);
    }

    public void getFatherMethod() {
        super.printName();
    }
}

Application.java

package oop.app.mysuper;

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println("引用父类成员变量");
        student.printName();
        //引用父类成员变量
        //name StudentName
        //this.name    StudentName
        //super.name   PersonName
        System.out.println("引用父类方法");
        student.getFatherMethod();
        //引用父类方法
        //PersonName

    }
}

引用父类构造器

只贴相关的代码块

Person.java

package oop.app.mysuper;

public class Person {

    public Person() {
        System.out.println("Person类 无参构造器");
    }


}

Student.java

package oop.app.mysuper;

public class Student extends Person{

    public Student() {
        System.out.println("Student类 无参构造器");
    }
}

Application.java

package oop.app.mysuper;

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        //Person类 无参构造器
        //Student类 无参构造器
    }
}

根据 Application.java 的运行结果,明显可以看出,在 Student 类实例化过程中,其无参构造器首先执行了父类Person的无参构造器,并且这一执行过程是最高优先级的,也即:

Student.java 源代码

package oop.app.mysuper;

public class Student extends Person{

    public Student() {
        super();
        System.out.println("Student类 无参构造器");
    }

}

上述代码块中的 super(); 如果手写,必须在子类无参构造器的第一行(当然不用写,默认就是在第一行),不放在第一行必然报错

构造器中的 this() 和 super()

  • 调用super()必须写在子类构造方法的第一行,否则编译不通过。每个子类构造方法的第一条语句,都是隐含地调用 super(),如果父类没有这种形式的构造函数,那么在编译的时候就会报错。

  • super() 和 this() 类似,区别是,super() 从子类中调用父类的构造方法,this() 在同一类内调用其它方法。

  • super() 和 this() 均需放在构造方法内第一行。

  • 尽管可以用this调用一个构造器,但却不能调用两个。

  • this 和 super 不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有 super 语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。

  • this() 和 super() 都指的是对象,所以,均不可以在 static 环境中使用。包括:static 变量,static 方法,static 语句块。

  • 从本质上讲,this 是一个指向本对象的指针, 然而 super 是一个 Java 关键字。

这个东西尤其是 this() 还很复杂,源码里面 this() 暂时还看不懂!

方法重写(Override)

重写,都是指方法的重写,和属性(成员变量)无关

在Java中,子类继承父类,父类的引用可以指向子类

这里必须保证: 父类子类的方法名一致、方法名前的修饰关键字一致

修饰关键字见结论

案例 (忽略构造器等,用不到的就懒得写了)

Person.java

package oop.app.myoverride;

public class Person {
    public void test() {
        System.out.println("Person => test()");
    }
}

Student.java

package oop.app.myoverride;

public class Student extends Person{
    public void test() {
        System.out.println("Student => test()");
    }
}

Application.java

package oop.app.myoverride;

public class Application {
    public static void main(String[] args) {
        Student student = new Student();
        student.test(); //Student => test()
        Person studentOverride = new Student();
        studentOverride.test(); //Student => test()
    }
}

鼠标在IDEA中悬停,发现

student 是 Student类 ---- public class Student extends Person

studentOverride 是 Person类 ---- public class Person

也就是方法的调用(对象的生成)只和 new 左边的类型有关。

IDEA中的快速重写方法

在子类(当前案例是 Student)中,使用快捷键 Alt + Insert 呼出 Generate 快捷菜单,选择 Override Methods

或者直接使用快捷键 Ctrl + O

选中上图的 test()方法后, Student 自动生成了代码块

Student.java

package oop.app.myoverride;

public class Student extends Person{
//    public void test() {
//        System.out.println("Student => test()");
//    }

    @Override
    public void test() {
        super.test();
    }
}

暂时理解为帮我写了注解 @Override

然后在当前的 test()方法中做对应修改

@Override
public void test() {
    System.out.println("Student => test()");
}

然后就发现执行结果与第一完全不一样

Student => test()
Student => test()

而当把父子类中的 test()方法都定义为静态方法时,Student 类不支持 IDEA快捷重写了,只能手写,

当然结果当然是会变的:

Student => test()
Person => test()

结论

  1. 当重写方法是静态方法 static时:方法没有被重写,对象的创建取决于 = new 左边

  2. 当重写方法非静态方法时:父类方法已经被子类覆盖了,而对象的创建依然取决于 = new 左边

  3. 修饰符:范围可以扩大但不能缩小

    • public > protected > default > private
  4. 抛出的异常:范围可以缩小,但不能扩大* 我不理解

为什么需要重写?

  • 父类的功能子类不一定需要,或者父类的功能不满足子类的需求;
posted @ 2021-12-15 15:13  jentreywang  阅读(192)  评论(0)    收藏  举报