在构造函数中实例化对象

时间:2012-02-14 19:09:16

标签: java

以下代码的结果似乎是相同的,所以我什么时候才能使用它们?

public class Person {
   public Person() {
       this.family = new Family();
   }
   Family family;
}

public class Person {
   Family family = new Family();
}

(我能想到的一个场景是,当有多个构造函数并且我们只想在其中一个内部创建一个族的实例时......这是唯一的情况吗?)

6 个答案:

答案 0 :(得分:6)

对于类变量 [静态变量],您不能使用第一个,因为您希望初始化只发生一次,而不是每次调用构造函数时都是如此。

例如变量,第二个只是第一个的合成糖。
有时你可能必须使用第二个 - for参数构造函数,它们本身 - 传递给你的构造函数。

答案 1 :(得分:5)

后者将保证每个人永远都有一个家庭(awww,不是那么好)。但在前者中,其他构造函数可能会被另一个开发人员添加,而这些开发人员会将Family保留为未初始化状态。这往往表明后者,更短的版本是更可取的。但事实并非如此,因为将Person建模为没有族,这可能是一个有效的条件,在这种情况下,通过构造函数初始化是优越的,因为你可以传递null。

第三种选择是具有提供的setter的(较长的,叹气)基本POJO样式,其中在显式调用setter之前不会初始化Family。 使用的更好的方法是,如果要为孤立建模,则不必为构造函数提供空值。

这一切都取决于你想如何约束人的建构。

答案 2 :(得分:3)

第一种方法为您提供了对如何初始化每个构造函数处理的类对象的自定义控制,而第二个选项将以相同的方式为所有构造函数初始化Family对象。

第一种方法更可取,因为它允许你将一个Family对象放入你的构造函数中,允许你做依赖注入这样的事情,这通常是很好的编程习惯(并且允许更容易的测试)。

除此之外,它们都是成员变量(不像其他人所说的那样是静态的,你必须使用静态关键字)。此类的每个实例都将以这种方式包含Family对象的实例。

我会推荐这样的东西

public class Person {
    public Person(Family family) {
       this.family = family;
  }
  Family family;
}

编辑: 为了解决关于我的帖子的评论(这在某种程度上是准确的),初始化对象的顺序存在差异。但是,评论指出,运作的顺序是:
实例变量的初始化 - >实例初始化程序 - >构造

从测试开始,似乎它取决于代码中首先出现的内容,实例变量或实例初始化器的初始化,以及然后在两者之后调用构造函数。考虑一下Family对象的构造函数只打印出给它的字符串的例子:

public class Person {
    {
        Family familyB = new Family("b");
    }
    Family familyA = new Family("a");

    Family familyC;
    public Person() { 
        this.familyC = new Family("c");
    }
}

在构造人物对象时产生此输出:
家庭:b
家庭:a 家庭:c

但是这段代码:

public class Person {
    Family familyA = new Family("a");
    {
        Family familyB = new Family("b");
    }

    Family familyC;
    public Person() { 
        this.familyC = new Family("c");
    }
}

在构造人物对象时产生此输出:
家庭:a 家庭:b
家庭:c

答案 3 :(得分:2)

我建议在子类化时使用第一个。考虑一下:

public class Child extends Person {
   public Child() {
        // super();
        // or
        this.family = new PatchWorkFamily();
   }
}

使用第二种初始化方法,您将始终初始化一个新族,然后根据需要覆盖它。这可能不是你想要的 - 如果这些对象在实例化时做了很多工作,则可能对性能有害。

答案 4 :(得分:1)

如果你计划扩展课程,第二种风格很糟糕(参见Daff的回答)。

对于实例变量,我认为维护程序员(通常是初级程序员)更清楚地在构造函数中执行所有实例级初始化。我推荐您选择1的变体。

public class Person
{
  private Family family;

  public Person()
  {
    family = new Family();
  }
}

我更倾向于在没有必要时避免使用this,因为它不会增加任何内容。

答案 5 :(得分:0)

我更喜欢第二种风格。如果你有多个构造函数,则不必重复初始化,也不会忘记它们。此外,它还清楚了如何初始化变量。通常,在阅读程序并遇到变量时,您首先要查看其声明。使用第二种样式,您可以立即看到默认值。对于第一个,您需要查看构造函数。

两者都没有计算优势。