【问题标题】:Does object in java created on heap before Constructor is invoked?在调用构造函数之前,java中的对象是否在堆上创建?
【发布时间】:2016-05-26 09:22:16
【问题描述】:

当从基类的构造函数调用被覆盖的方法时,根据运行时多态性概念,子类中定义的方法也会被调用。我想知道这是如何在 JVM 中处理的,当控制在基类构造函数中时,子类的构造函数尚未被调用,因此 Object 尚未完全构造。

我了解从基类构造函数调用覆盖方法的不良影响,但只是想了解这是如何实现的。

我觉得堆中的对象是在调用构造函数之前创建的,并且在调用构造函数时,属性会被初始化。请提供您对上述内容的宝贵意见。

下面是演示相同的代码。

Base.java

public class Base {
    public Base() {
            System.out.println("Base constructor is executing...");
            someMethod();
    }

    public void someMethod() {
            System.out.println("someMethod defined in Base class executing...");
    }
}

Sub.java

public class Sub extends Base{
    public Sub() {
            System.out.println("Sub constructor is executing...");
    }
    @Override
    public void someMethod() {
            System.out.println("someMethod defined in Sub class executing...");
    }
}

Client.java

public class Client {
    public static void main(String[] args) {
            Sub obj = new Sub();
    }
}

控制台输出

基础构造函数正在执行...

在子类中定义的someMethod正在执行...

子构造函数正在执行...

【问题讨论】:

  • 简短的回答是肯定的。使用dup 操作码创建新对象实例,仅在此之后调用构造函数。您也可以创建自己的对象而无需调用构造函数,例如使用反序列化。
  • @nits.kk,看看这篇文章:artima.com/designtechniques/initializationP.html

标签: java inheritance constructor heap-memory


【解决方案1】:

java中的对象是在构造函数被调用之前创建的吗?

是的,否则您将没有要初始化的对象。

在字节码层面,先创建对象,然后调用构造函数,传入对象进行初始化。构造函数的内部名称是<init>,它的返回类型总是void,这意味着它不返回对象,只初始化它。

注意:Unsafe.allocateInstance 将在不调用构造函数的情况下创建对象,对于反序列化很有用。

【讨论】:

  • 相关JLS参考:The new object contains new instances of all the fields declared in the specified class type and all its superclasses. As each new field instance is created, it is initialized to its default value (§4.12.5).
  • @nits.kk 它是为final 字段完成的,但是检查非最终字段意味着检查类的使用方式,这要复杂得多,可能无法解决。例如您必须检查是否在所有可能的代码路径中的 getter 之前调用了字段的 setter。
  • @nits.kk 局部变量只“存在”从它们第一次被赋值到它们被声明的块结束。每次有人调用该方法时,他们都会看到他们的局部变量的自己的值。虽然从创建对象到收集对象的那一刻起就存在字段,但每个人都看到相同的字段。 (虽然在多线程上下文中并不总是相同的值,但这是完全不同的蠕虫罐头。)但理论上局部变量也可以自动初始化为null0false,只是决定他们不会的。
  • @biziclop 如果编译器/IDE 可以为您检测到不安全的线程访问并自动修复它,我想我们会失业。 ;)
  • @PeterLawrey 哈哈,很有可能。 :) 不,我的意思是相反,他们本可以决定不检查局部变量是否总是在读取之前写入,而只是在声明时将它们初始化为默认值。不过情况会更糟。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-07
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多