在创建新的子类对象时,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是相同的。这意味着只有一个实例?
答案 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