2

我们有以下代码:

class Parent {
    public int i = 5;
}

class Son extends Parent {

}

public class MyTest {

    public static void main(String[] args){
        **Son son = new Son();**
        System.out.println(son.i);

    }

}

执行Son son = new Son()时,以下问题让我感到困惑:

  1. 是否会在内存中创建实例?我知道在创建Son实例之前,将调用不带参数的Parent默认构造函数,正确调用构造函数和创建实例是不同的东西吗?
  2. 如果没有创建Parent实例,但存储在Son实例中的字段在哪里?因为我们可以通过儿子参考获得i的价值?

非常感谢!!!

4

3 回答 3

2

是否会在内存中创建父实例?我知道在创建 Son 实例之前,将调用不带参数的 Parent 默认构造函数,正确调用构造函数和创建实例是不同的东西吗?

Parent不会创建的实例,实际上Parent会调用 的构造函数。构造函数只是 JVM 在创建实例时运行的特殊代码块。没有规则说“在创建 的实例时T,只能T运行 的构造函数”。

如果没有创建 Parent 实例,但我存储在 Son 实例中的字段在哪里?因为我们可以通过儿子参考获得 i 的价值?

仅仅因为它没有写在源代码中,并不意味着它不存在。通过编写Son extends Parent,您是在告诉编译器和运行时(除其他外)Son确实有一个名为 的字段i,因此您不必在Son. 这是继承的主要目的之一——减少重复代码。

于 2019-12-26T02:19:12.187 回答
0

当您创建子类的实例时,必须调用超类构造函数来初始化超类字段,在本例中为son.i. 当超类没有给定构造函数时,Java 会隐式创建一个默认构造函数,等效于以下代码:

public Parent() {}

Parent扩展时, 的构造函数Son通过调用 的构造函数开始,Parent通过以下代码隐式完成:

public Son() {
    super() // Calls Parent()
}

简而言之,是的。子类确实为内存中的超类生成字段。将子类视为具有一些花里胡哨的父类。例如:

Parent myObj = new Son();
System.out.println(myObj.i); // Still prints 5 because i is still a variable of son
于 2019-12-26T02:22:45.513 回答
0

问题1:是的,如果你还没有创建一个默认的Parent构造函数,Java会自动创建一个默认的Parent构造函数,并且每次创建一个新的Son对象时,Parent构造函数也会被调用。您可以通过在 Son 构造函数的第一行调用 super(...) 来显式调用您选择的 Parent 构造函数(假设您已经定义了一个或多个)。

问题 2:字段“i”是 Parent 类的一部分。您目前编写它的方式(具有公共访问权限)将可供 Son 类和其他任何想要更改它的人访问。

进一步的评论:将字段设置为类的私有字段是一种很好的编程习惯,如果可能的话,将其设为最终字段。

于 2019-12-26T02:23:25.817 回答