首先创建一个对象,然后执行它的构造函数吗?

时间:2014-06-23 13:39:42

标签: java oop constructor

我的问题是

A a=new A();

这是首先创建的对象,然后调用构造函数方法? 或者创建对象是因为构造函数方法被调用?

如果对象需要调用构造函数,这意味着应该在调用构造函数之前创建对象,如果我将构造函数声明为私有(只是为了查看它是否在没有构造函数的情况下工作),那么我得到错误。

现在如果构造函数执行创建了对象,我就无法理解逻辑上是如何工作的,我的意思是如果没有对象,对象的方法怎么能执行呢?

有人可以解释一下吗?

7 个答案:

答案 0 :(得分:12)

在调用构造函数之前,为对象分配内存,是的。

您可以通过以下步骤来考虑它:

  1. 为对象分配内存。
  2. 执行各种构造函数(总是从层次结构的顶部到最具体的构造函数,例如,Object首先执行构造函数,然后执行其他任何超类,然后执行实际课程。
  3. 所以对象已经有了内存,它被构造函数初始化,而不是被创建。构造函数只是设置对象的状态
  4. 在构造函数执行完毕之前,该对象不可用。
  5. 第4点实际上并不完全正确,因为你可以通过将this传递给构造函数中的另一个方法来泄漏对象的引用,但这有点像边缘情况。这是一种引人入胜的现象,因为您可以在final变量初始化之前访问这些变量并从中检索两个不同的值,具体取决于它们在执行中的位置。

    解决以下评论:构造函数本身并没有返回任何内容。它具有void返回类型。变量实际上如何接收对象并不像你想象的那样简单,而且这是一个非常好的问题。您可以在以下Stack Overflow答案中阅读有关此主题的非常详细的答案,这些答案比我在此处复制的工作做得更好,更彻底。

    作为旁注,正如Peter Lawrey在评论中提到的那样,您可以使用Unsafe API来创建对象的实例而无需执行构造函数。然而,根据some other Stack Overflow discussions,一般意见似乎是你用Unsafe做的任何事情都不符合普通的Java行为。

答案 1 :(得分:3)

您使用多种语言标记了问题,您应该选择一种语言。

但惯例是首先为对象及其字段分配内存,然后运行构造函数然后,(如果适用),将对此新对象的引用分配给变量a

存在一些细微差别。例如,C#对值类型的处理方式略有不同。

  1. 为值类型实例
  2. 分配内存
  3. 运行构造函数
  4. 将对象逐位复制到指向的位置a
  5. 这可以确保a永远不会指向值类型的部分构造的实例。它还确保,如果构造函数抛出异常,指向的内存位置a不会被破坏。

答案 2 :(得分:3)

回答C ++:

new-expression(让我们说new A())编译如下:

1检查上下文中是否可以访问A的默认构造函数;否则,表示编译错误。

2a如果类A具有重载分配函数A::operator new(),则调用它以获取对象的空间。

2b否则,调用分配函数::operator new()以获取对象的空间。

3在从分配函数获得的空间中调用默认构造函数A::A()

答案 3 :(得分:0)

Class具有创建对象的构造函数。您在不在对象上的类上调用构造函数,因此始终从类构造函数创建新对象。

答案 4 :(得分:0)

new运算符通过为新对象分配内存并返回对该内存的引用来实例化一个类。所以实例化一个类意味着与创建一个对象相同,当你创建一个对象时,你正在创建一个类的实例,因此“实例化”一个班级。

答案 5 :(得分:0)

我一般同意@dcastro。但是,我相信在两种语言中,在执行构造函数之前(或至少在构造函数中的第一行代码之前)填充任何内联分配的实例字段。因此,您可以得出结论,首先创建对象,然后调用构造函数。

class MyClass{
    final int value1 = 15;
    final int value2;

    public MyClass(){
          this.value2 = value1;
    }
}

在这两种语言中,我认为value2将设置为15.因此,请将1a - populate in-line instance fields添加到dcastro's答案。

答案 6 :(得分:0)

构造函数实际上不会创建对象。它们更像初始化器。他们将数据设置为JVM提供给它们的对象。