Java基础之super关键字浅析

目录
  • 一、定义
  • 二、应用
    • 2.1    应用范围
    • 2.2    用法
      • 2.2.1    在子类中调用父类的属性或方法
      • 2.2.2    在子类中指代父类构造器
  • 附:super实际使用示例
    • 总结

      本文重点介绍super关键字,在Java中的作用以及用法。

      一、定义

      它是一个指代变量,用于在子类中指代父类对象。

      二、应用

      2.1    应用范围

      只能用于子类的构造函数和实例方法中,不能用于子类的类(静态)方法中。原因是super指代的是一个父类的对象,它需要在运行时被创建,而静态方法是类方法,它是类的一部分。当类被加载时,方法已经存在,但是这时候父类对象还没有被初始化。

      2.2    用法

      在Java中super有两种使用场景。

      2.2.1    在子类中调用父类的属性或方法

      在子类中调用父类的属性或方法。特别是子类中有与父类相同的属性或者方法,那么这时如果你想调用父类的属性或者方法,那么你必须使用super关键字。因为子类中和父类中的属性或方法同名,则父类中的方法或属性将被覆盖或隐藏。super可以指代父类中的类属性和类方法,但是并不建议这么用,虽然不会报错,但是说明你对static关键字还不够了解。请认真查看并理解static关键字。

      public class Parent {
          public String name = "小头爸爸";
          public boolean hasMoney = false;
       
          public void sleeping(){
              System.out.println("爸爸已经睡了");
          }
       
          public void working(){
              System.out.println("爸爸正在工作。。。");
          }
      }
       
      public class Child extends Parent {
       
          public String name = "大头儿子";
       
          /**
           * 当子类和父类有属性重名时,需要super才能调用到父类的属性,
           * 直接调用会调用到子类的属性
           * 如果不重名,可直接调用且调用的是父类的属性
           */
          private void testParam(){
              System.out.println("爸爸的名字叫" + super.name);
              System.out.println("孩子的名字是" + name);
              System.out.println("爸爸是否有有钱:" + hasMoney);
          }
       
          /**
           * 方法和上面的属性结果一样
           */
          public void testMethod(){
              sleeping();
              super.sleeping();
              super.working();
          }
       
          public void sleeping(){
              System.out.println("儿子已经睡了");
          }
       
          public static void main(String[] args) {
              Child child = new Child();
              child.testParam();
              child.testMethod();
          }
      }

      测试结果:

      =============

      爸爸的名字叫小头爸爸
      孩子的名字是大头儿子
      爸爸是否有有钱:false
      儿子已经睡了
      爸爸已经睡了

      爸爸正在工作。。。

      ============

      2.2.2    在子类中指代父类构造器

      在Java中,子类是父类的派生类,它的实例化依赖于父类的实例化。所以它的任何一个构造函数都必须要初始化父类,Java就是super关键字调用父类构造方法,来完成这个操作。

      有人会奇怪,那为什么在2.1.1的例子,父类没有构造方法,子类也没有构造方法,难道在某些情况下,实例的初始化并不依赖于构造函数?

      答案是,实例的初始化必须要构造函数。2.2.1没有构造函数的原因是,在Java类定义中,如果开发者没有显示的定义构造函数,那么Java会隐式的为该类定义一个无参构造函数。但是如果开发者自己定一个构造函数(无论有参还是无参),那么Java就不会再为该类隐式的定义一个无参构造函数了。

      那么还原构造函数后的代码:

      public class Parent {
          ...
          public Parent() {
          }
          ...
      }
       
      public class Child extends Parent {
          ...
          public Child() {
          }
          ...
      }

      那么又有人有奇怪了,你不是说子类的实例化依赖于父类的实例化,那么在子类的构造函数中应该需要调用super来初始化父类不是吗?

      是的,在我们子类的构造函数中,如果我们没有显式调用super来初始化父类的话,那么Java会隐式的调用super();来调用父类无参构造函数并把它放在构造函数的第一行。记住哦,Java只会隐式的调用无参构造函数,如果父类没有无参构造函数,那么子类中就必须显示的调用super关键字来调用已有的有参构造函数来初始化父类。

      public class Parent {
          public String name = "小头爸爸";
          public Parent(int age) {
          }
       
          public void sleeping(){
              System.out.println("爸爸已经睡了");
          }
      }
       
      public class Child extends Parent {
          public String name = "大头儿子";
          public Child() {//如果没有super来初始化父类,同样也会报错
      //        super();//编译期报错,因为父类并没有无参构造函数
              super(15);//正确打开方式
          }
       
          private void printParentName(){
              System.out.println("爸爸的名字叫" + super.name);
          }
       
          private void parentStatus(){
              super.sleeping();
          }
      }

      子类中的super为什么必须要放在第一行?因为子类的实例化依赖于父类的实例化,在构建子类时,必须要有父类实例,只能有了父类的实例,子类才能够初始化自己。就好像人类世界里,都是要先有父亲,再有孩子一样。

      附:super实际使用示例

      下面来看看super关键字的实际用法。 在这里,Emp类继承了Person类,所以Person的所有属性都将默认继承到Emp。 要初始化所有的属性,可使用子类的父类构造函数。 这样,我们重用了父类的构造函数。

      class Person {
          int id;
          String name;
      
          Person(int id, String name) {
              this.id = id;
              this.name = name;
          }
      }
      
      class Emp extends Person {
          float salary;
      
          Emp(int id, String name, float salary) {
              super(id, name);// reusing parent constructor
              this.salary = salary;
          }
      
          void display() {
              System.out.println(id + " " + name + " " + salary);
          }
      }
      
      class TestSuper5 {
          public static void main(String[] args) {
              Emp e1 = new Emp(1, "ankit", 45000f);
              e1.display();
          }
      }

      结果如下:

      1 ankit 45000

      总结

      super关键字指代父类对象,主要用于在子类中指定父类的方法和属性,也用于在子类中初始化父类。子类的静态方法中不能使用super关键字。

      本文转自网络,如有侵权请联系客服删除。