创建新的子类对象时是否存在超类实例?

时间:2014-06-16 14:15:28

标签: java

在创建新的子类对象时,JVM是否会创建超类实例?在下面的示例中,为什么super.setName("Buddy")会成功?创建Pet后是否有new Dog()的实例?

public class MainDemo {
    public static void main(String[] args) {
        Pet pet = new Dog();
        System.out.println(pet.getName());//it will print Buddy
    }
}
public class Pet {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public class Dog extends Pet {
    public Dog() {
        super.setName("Buddy");
    }
}

我改变了Dog and Pet的构造函数,如下所示

public Pet() {
    System.out.println("this is Pet's constructor");
}
public Dog() {       
    super.setName("Buddy");
    System.out.println("this is Dog's constructor");
}

控制台中的结果是

this is Pet's constructor
this is Dog's constructor
Buddy

看起来jvm会创建一个Pet?

我再次将代码添加到Pet and Dog中,如下所示

System.out.println(this.getClass().getName()+".hashCode="+this.hashCode());

结果是

this is Pet's constructor
com.bt.java.project.Dog.hashCode=27189676
this is Dog's constructor
com.bt.java.project.Dog.hashCode=27189676
Buddy

他们的hashCode是相同的。这意味着只有一个实例?

3 个答案:

答案 0 :(得分:6)

执行时

new Dog()

只有一个对象是物理创建的,即Dog类的实例。但是,此实例还包含所有必需的信息,以便可以将其用作Pet。它继承了Pet中包含的所有非私有字段/方法,但也可以添加特定于狗的其他字段/方法。出于这个原因,一个对象也被称为其所有超类的一个实例,但这并没有改变只创建一个对象的事实(我认为这是你的问题,从根本上说)。

您应该想到这样的Dog对象:

+---------------+
|  +---------+  |
|  | Pet     |  |
|  | fields  |  |
|  | and     |  |
|  | methods |  |
|  +---------+  |
|               |
|  Dog          |
|  fields       |
|  and          |
|  methods      |
+---------------+

它仍然是一个对象,但您可以将其视为Pet,只考虑最内层的Pet区域上图。

答案 1 :(得分:1)

Dog extends Pet。这意味着狗是宠物。因此,你的班级狗拥有宠物的所有方法,并且可以使用它们(至少是公共的和受保护的)。

您可能希望从有关类和OOP的教程开始。

并回答你的问题:是的,有一个Pet创建的实例(它与Dog的实例相同)。你不能拥有一只不是宠物的狗。可能是非宠物的宠物。

例如,你可以这样做:

Pet pet = new Dog();

你的宠物将是一只狗(狗的一个例子),但是你只能从Pet中调用这些方法,除非你将它投射到像这样的狗:

((Dog)pet).someMethodOnlyInDogAndNotInPet();

你甚至可以这样做:

Object obj = new Dog();

因为所有对象都是从Object派生的。我强烈建议不要这样做。

答案 2 :(得分:1)

是的,有一个实例Pet,但它与实例Dog相同。你可以这样做:

    Dog dog = new Dog("Bleeker");
    Pet myPet = (Pet) dog;
    Pet pet = new Pet("Buddy");

    // this will print the same Object ID twice:
    System.out.println(dog);
    System.out.println(myPet);

    // this will print a different Object ID:
    System.out.println(pet);

如果你改变了这样的实现:

public class Pet {
    private String name;

    public Pet(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class Dog extends Pet {

    public Dog(String name) {
        // call to constructor of Pet, initializing a Pet instance
        super(name);
        // completion of constructor of Dog, initializing a Dog instance.
    }
}

然后:

System.out.println(dog.getName()); // will print Bleeker
System.out.println(myPet.getName()); // will print Bleeker
System.out.println(pet.getName()); // will print Buddy