【问题标题】:What is the difference between this() and new Object() inside a overloaded constructor?重载构造函数中的 this() 和 new Object() 有什么区别?
【发布时间】:2021-02-06 15:06:41
【问题描述】:

我有以下代码:

public Account() { #1
    id = 0;
    balance = 0;
    interestRate = 4.5;
}

public Account(int newId, double newBalance) {
    //this(); - option 1
    //new Account(); - - option 2
    id = newId;
    balance = newBalance;
}

public Account(int newId) { #2
    new Account();
    id = novoId;
}

使用Account account = new Account(int); 创建对象时,它会从#2 到#1 到#2。

问题是选项 1 和选项 2 似乎呈现相同的行为(通过调试器查看),这似乎有点违反直觉。有人能解释一下吗?

【问题讨论】:

  • 这两个示例的行为不应相同。在 Account 的构造函数中创建一个新的 Account 将开始递归创建,直到堆栈用完。
  • @NomadMaker 在这种情况下,不会递归创建 Account 实例,因为 new Account(); 将调用无参数构造函数,并且在该构造函数内部没有构造函数调用。
  • @Yousaf new Account() 怎么样?
  • @NomadMaker 怎么样? OP 在实例中使用new Account(int); 创建,所以new Account() 只会被调用一次。

标签: java oop object constructor


【解决方案1】:

查看您的代码,您的意图似乎是当您创建 Account 类的实例时

Account account = new Account(int);

您想使用Account 类中的无参数构造函数初始化实例,正确的方法是使用第一个选项,即this()

为什么第一个选项是做你想做的正确方法的原因是因为

this();

这将调用无参数构造函数来继续初始化新创建的实例,但是

new Account();

将创建Account 类的新实例,这显然会导致调用无参数构造函数,这可能不是您想要的。

因此,第一个选项将调用无参数构造函数来初始化 Account 类的新创建实例,而第二个选项将创建一个 Account 类的新实例,该实例将与导致的实例完全不同首先调用构造函数。

【讨论】:

    【解决方案2】:

    这两个方法都调用默认构造函数。

    • 使用“this()”调用当前实例的构造函数
    • 使用“new Account()”,您正在通过调用其默认构造函数来创建一个新实例。

    第一个选项是正确的,因为我假设你想设置当前实例的所有变量。

    【讨论】:

      【解决方案3】:

      区别非常重要:this() 会将当前对象的创建/初始化链接到无参数构造函数Account(),而new Account() 将创建 第二个 类型的对象Account 使用无参构造函数Account(),然后马上扔掉。

      例如,用:

      public Account(int newId) {
          new Account();
          id = novoId;
      }
      

      打电话,new Account(5),就可以了

      1. 创建帐户类型的对象#1
      2. 为 object#1 调用构造函数 Account(int) 并使用 5
      3. 创建帐户类型的对象#2
      4. object#2 调用构造函数 Account()
      5. object#2 设置 id=0、balance=0、interestRate=4.5
      6. (步骤 4 的结束构造函数)
      7. (返回第2步的构造函数)
      8. 为对象#1 设置 id=5
      9. (结束第 2 步的构造函数调用)

      最终结果:创建的对象的 id=5,balance=0(默认),interestRate=0(默认)

      public Account(int newId) {
          this();
          id = novoId;
      }
      

      致电new Account(5) 即可

      1. 创建帐户类型的对象#1
      2. 为 object#1 调用构造函数 Account(int) 并使用 5
      3. 为对象#1 调用构造函数 Account()
      4. 为对象#1 设置 id=0、balance=0、interestRate=4.5
      5. (步骤 3 的结束构造函数)
      6. (返回第2步的构造函数)
      7. 为对象#1 设置 id=5
      8. (结束第 2 步的构造函数调用)

      最终结果:创建的对象有 id=5, balance=0, interestRate=4.5

      因此,一个重要的区别是,当您在构造函数中使用this() 时,您使用new Account(int)new Account(int, double) 创建的对象的interestRate 将被初始化为4.5,但在使用new Account() 时在您的构造函数中,它将为 0(假设您在声明本身中没有初始化)。

      就个人而言,我建议将您的构造函数更改为:

      public Account(int newId, double newBalance) {
          id = newId;
          balance = newBalance;
          interestRate = 4.5;
      }
      
      public Account() {
          this(0, 0);
      }
      
      public Account(int newId) {
          this(newId, 0);
      }
      

      这就是——在我看来——更清晰,并建立一个清晰的初始化顺序。

      【讨论】:

      • 我就是这么想的。混乱源于代码另一部分中对 interestRate 的静态初始化。非常感谢您的澄清。
      • @IgorKolesnikov 那不是静态初始化,那只是初始化。静态初始化涉及使用static { ... } 或直接初始化静态字段。这也是为什么在提问时发布minimal reproducible example 很重要的原因。
      猜你喜欢
      • 2014-02-10
      • 2012-03-10
      • 1970-01-01
      • 2011-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-30
      • 1970-01-01
      相关资源
      最近更新 更多