【问题标题】:how to understand super in java如何理解java中的super
【发布时间】:2013-09-01 12:38:37
【问题描述】:

我遇到了一个让我很困惑的问题,就是关键字'super',我的测试代码是这样的:

package test;

public class Parent {
   private String name;

   public Parent(){
        this.name = "parent";      
   }

    public String getName() {
        return name;
    }

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

    public void showName(){
        System.out.println(this.name);
    }

}


public class Child extends Parent{

    public Child(){
        this.setName("Child");
    }

    public void showName(){
        System.out.println(super.getClass().toString());
        System.out.println(super.toString());

        super.showName();
        System.out.println(super.getName());
    }
}

public class Test {

    public static void main(String[] args) {
        Child d = new Child();
        d.showName();    
    }
}

所以结果是这样的:

class test.Child
test.Child@2207d8bb
Child
Child

我对'super'的理解是它是对当前实例的父实例的引用,所以我期望的输出就像'Parent',从结果来看,我错了,它就像当前实例调用父方法,并且'super'不是父实例,我的理解正确吗?有没有办法让父实例只初始化子类?

【问题讨论】:

    标签: java properties super


    【解决方案1】:
    class Animal {
      void eat() {
        System.out.println("animal : eat");
      }
    }
    
    class Dog extends Animal {
      void eat() {
        System.out.println("dog : eat");
      }
      void anotherEat() {
        super.eat();
      }
    }
    
    public class Test {
      public static void main(String[] args) {
        Animal a = new Animal();
        a.eat();
        Dog d = new Dog();
        d.eat();
        d.anotherEat();
      }
    

    }

    输出将是

    动物:吃 狗:吃 动物:吃

    第三行打印“animal:eat”,因为我们调用了 super.eat()。如果我们调用 this.eat(),它会打印为“dog:eat”。

    【讨论】:

    • 没有解决实际问题。
    【解决方案2】:

    您已经使用了四个使用 Child 对象调用的打印语句:

    1. System.out.println(super.getClass().toString()); 由于 getClass() 是 final 方法,因此它不能被覆盖,所以当你调用 super.getClass() 时,你实际上调用了 Object 类的 getClass(),它返回实际调用对象的类的名称。

    2. System.out.println(super.toString()); 这里再次调用 Object 类的 toString() 方法,该方法返回 "getClass().getName() + "@" + Integer.toHexString(hashCode());" 但是,如果您在父类中重写此方法,您肯定会执行该版本

    3. super.showName(); 此方法返回“Child”....原因如下:当您创建 Child 类的对象时,构造函数运行如下 -

      公共孩子(){ 极好的(); // 即使你没有写 this,编译器也会隐式调用 this this.setName("孩子"); }

      因此发生以下操作 - 1. 调用父类的构造函数,将“名称”设置为“父”。 2. Child 类的构造函数现在用“Child”覆盖这个值。 所以实例变量'name'的值是'Child'。

    4. System.out.println(super.getName()); 这里如第 3 点所述,只有一个对象和一个实例变量 'name',其值为 'Child'。

    【讨论】:

      【解决方案3】:

      从 javadocs,getClass 返回对象的运行时类

      对象的运行时类是“Child”。

      由于你没有覆盖getClass()(你不能因为它是final),所以super.getClass() 的行为与getClass() 完全一样。调用 Object 类的getClass 方法。

      如果您想打印 Parent,请致电 getClass().getSuperclass()

      【讨论】:

        【解决方案4】:

        我对“super”的理解是它是对当前实例的父实例的引用

        不 - 没有“父实例”这样的东西。当你创建一个实例时,只会创建一个一个对象——Child的一个实例,它也继承了Parent的所有字段和方法。

        super有两种使用方式:

        • 引用方法的超类实现,通常是在您覆盖子类中的方法时。这就是您在 Child.showName 中所做的 - 它正在调用 Parent.showName,但是在同一个实例上(因为那里只有一个实例)
        • 从子类构造函数调用超类构造函数

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-15
          • 1970-01-01
          • 1970-01-01
          • 2014-11-01
          • 2023-03-10
          • 1970-01-01
          相关资源
          最近更新 更多