如何在java中理解super

时间:2013-08-29 07:34:24

标签: java properties super

我遇到了一个困扰我的问题,它是关键字'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',从结果来看,我错了,就像当前实例调用父方法一样,'超级'不是父实例,是我的理解对吗?有没有办法让我只能初始化Child类的父实例?

4 个答案:

答案 0 :(得分:7)

  

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

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

super有两种使用方式:

  • 要引用方法的超类实现,通常是在重写子类中的方法时。这就是您在Child.showName中所做的事情 - 它正在调用Parent.showName,但在同一个实例上调用 (因为 只有一个实例)< / LI>
  • 从子类构造函数
  • 调用超类构造函数

答案 1 :(得分:2)

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

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

由于您未覆盖getClass()(您不能,因为它是final),因此super.getClass()的行为与getClass()完全相同。调用Object类的getClass方法。

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

答案 2 :(得分:0)

您使用了使用Child对象调用的四个print语句:

  1. 的System.out.println(super.getClass()的toString()); 由于getClass()是final方法,因此无法重写,因此当您调用super.getClass()时,实际上会调用Object类的getClass(),它返回实际调用对象的类的名称。 / EM>

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

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

    public Child(){    超(); //即使您没有编写此,编译器也会隐式调用它    this.setName( “孩子”); }

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

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

答案 3 :(得分:-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”。