0

我遇到了一个让我很困惑的问题,就是关键字'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' 不是父实例,我的理解对吗?有没有办法让父实例只初始化子类?

4

4 回答 4

8

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

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

super有两种使用方式:

  • 引用方法的超类实现,通常是在您覆盖子类中的方法时。这就是你正在做的事情Child.showName- 它正在调用Parent.showName,但是在同一个实例上(因为只有一个实例)
  • 从子类构造函数调用超类构造函数
于 2013-08-29T07:38:56.350 回答
2

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

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

由于您没有覆盖getClass()(您不能因为它是final),所以super.getClass()行为与getClass(). getClass对象类的方法被调用。

如果要打印父级,请致电getClass().getSuperclass()

于 2013-08-29T07:40:21.760 回答
0

您使用了四个使用 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 类的对象时,contructor 运行如下 -

    公共儿童(){超级();// 即使你没有写 this.setName("Child"); 编译器也会隐式调用 this.setName("Child"); }

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

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

于 2013-09-02T07:24:44.257 回答
-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”。

于 2014-05-20T07:56:33.003 回答