【问题标题】:Where is super class fields stored in sub class? [duplicate]超类字段存储在子类中的什么位置? [复制]
【发布时间】:2019-12-26 02:10:52
【问题描述】:

我们有以下代码:

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. 是否会在内存中创建 Parent 实例?我知道在创建Son实例之前,会调用Parent不带参数的默认构造函数,正确调用构造函数和创建实例是不同的东西吗?
  2. 如果没有创建 Parent 实例,但 i 字段存储在 Son 实例中的什么位置?因为我们可以通过 son 参考获得 i 的价值?

非常感谢!!!

【问题讨论】:

标签: java


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    当您创建子类的实例时,必须调用超类构造函数来初始化超类字段,在本例中为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
    

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-01
        • 2020-04-01
        • 2011-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        相关资源
        最近更新 更多