继承:对象创建

Rol*_*all 10 java inheritance instantiation instance-variables

假设我有这段代码:

class Animal {
    int legs = 4;
    int head = 1;
}

public class Dog extends Animal {
    public static void main (String []args) {
        Dog dog = new Dog();
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道super()隐式置于no-args构造函数的第一行,所以我知道Animal构造函数将被执行,因此Animal将设置实例变量.

为了这个目的,我想,了解如果一旦这些变量已经被超级构造函数(初始化Animal),这些实例变量会在动物对象有保留或复制到子类(Dog).

在第一种情况下,对象Animal将被隐式实例化,super();并且每当实例Dog需要访问其中一个变量时,它将访问实例中保存的变量Animal(在后台创建).或者第二种情况,如果对象Animal将被临时创建,则将所有实例变量(in Animal)复制到Dog实例,然后删除Animal临时创建的实例.

我个人认为,例如,一个Dog对象将直接链接到一个Animal直接连接到一个对象的对象.

是这样的吗?

Jon*_*eet 16

只有一个对象,它立即(从一开始就是)一个Dog实例.它有所有的领域Dog(不是你在这里)所有的领域Animal.

最初,所有变量都将设置为默认值(0,null等).然后,当您到达每个类的构造函数体(在调用超类构造函数之后)时,将执行实例变量初始值设定项,然后执行该类的构造函数体.

不需要复制,因为只有一个对象.例如,如果您要编写如下Animal构造函数:

public Animal() {
    System.out.println(this.getClass());
}
Run Code Online (Sandbox Code Playgroud)

...它会打印出来Dog,因为该对象已经是一个Dog,即使它的Dog构造函数还没有被执行.

  • @GaborSch:我认为*zvzdhk可能指的是响应速度,而不是提出技术问题.当然,我可能是错的. (6认同)
  • 你好吗? (2认同)
  • @zvzdhk因为对象本身就是一个"狗".即使在构造函数中(也在`super`构造函数中)`this`指的是当前对象.所以看起来很奇怪,但它很简单. (2认同)
  • @Rollerball实际上分配了一个对象,包含超类和子类的所有属性.它是一个连续的存储区域,超级成员位于开头,子成员位于存储区域的末尾.然后初始化这些成员(例如`head = 1`),然后调用构造函数.请记住,应该首先调用`super()`作为第一个调用,所以它首先使用`Object()`然后`Animal()`以`Dog()`开头. (2认同)

gab*_*sch 9

您的Dog扩展Animal,并且head,legs变量是不是私人的,所以你会在访问这些Dog实例.

在实践中,会发生以下情况:

  • 您创建一个Dog实例,也是一个Animal
  • 创建并初始化所有对象属性(包括head和之后的属性Animal)
  • 隐式构造函数Dog被调用(它调用super())
  • 隐式构造函数Animal被调用

结果是一个对象,它是一个Dog,但也隐含着一个Animal.


一个如何Dog对象看起来像(让我们忘掉Object类的例子的缘故).我们假设Dog也有一个public String name;属性.

这是Dog实例的内存映射:

Addr  Type     Name      Defined in:
------------------------
| 0 | int    | legs    | Animal
| 1 | int    | head    | Animal
| 2 | String | name    | Dog
------------------------
Run Code Online (Sandbox Code Playgroud)
  • 如果你有Animal,你可以访问地址1head的变量,
  • 如果您有Dog,则访问地址2name处的变量,
  • 如果您有Dog,则head地址1处访问变量

Animal类体中运行的代码只能看到地址0-1.在Dog类中运行的代码可以访问地址0-2.如果属性是private超类,则该子地址将被禁止该地址.

这种内存映射可以非常容易地向下转换对象:使用相同的内存映射,只有处理(代码和可见性)不同.

我希望它澄清一点.