声明初始化和构造函数初始化之间的区别

时间:2013-02-25 11:29:37

标签: java variables constructor

以下两个之间有什么区别,哪个更好?

public class foo {

    int i = 2;

}

public class foo {

  int i;
    foo() {

        i = 2;

    }
}

5 个答案:

答案 0 :(得分:3)

在您的示例中,行为语义没有区别。在Java中,所有实例字段初始化器(和实例块)在超类初始化之后执行构造函数体之前执行;见JLS 12.5

不同之处在于代码可读性和(在其他示例中)避免重复编码和脆弱性 1 。这些需要根据具体情况进行评估。

值得注意的是,在某些情况下你必须在构造函数中进行初始化;即当初始化取决于构造函数参数时。


1 - 重复性和脆弱性问题是同一件事的另一面。如果您有多个构造函数,那么“构造函数初始化”方法往往会导致重复。如果添加额外的字段,可以将初始化添加到所有相关的构造函数;即脆弱。

答案 1 :(得分:1)

如果你有两个或更多的构造函数,并且每个构造函数的初始化值不同,那么你应该使用构造函数初始化,因为没有办法对成员初始化做同样的事情......

但是如果你只有一个构造函数......你可以使用成员初始化来获得更好的代码清晰度..

答案 2 :(得分:0)

在你的第一个例子中,我是类foo的实例变量(更好的名字是Foo)。它是在课堂加载时初始化的。

在你的第二个例子中,我也是一个实例变量,但在这种情况下,在foo()构造函数中初始化。

这里没有真正的区别,尤其是原语。

但是,在多线程环境中,如果您打算在构造函数中初始化ivars,并且这些ivars是非原始的,则需要避免暴露部分构造的对象的风险。原因是构造函数不同步且不能应用synchronised关键字,但是两个线程无法构造同一个对象。

因此,为避免这种情况,您不应在构造函数中公开this。这样做的一种方法是调用非最终方法。这样做,比如调用抽象方法,允许一些未知代码对未完成的对象执行某些操作。显然,如果你在声明中初始化,就无法做到这一点。

P.S。我认为在 Effective Java 中有一些东西,但找不到任何东西。

答案 3 :(得分:0)

首先,我认为第二个例子应该是这样的:

public class foo{

  int i;
  foo(){

     i = 0;

  }

}

否则我只是C'tor范围内的局部变量。 其次,第一个例子显示了在调用类C'tor之前调用的初始化。如果您希望这种情况发生,无论使用何种C'tor,这都是很好的。 它还使您能够将我声明为只读。

答案 4 :(得分:0)

特别是在这种情况下,这两种变体没有区别。第一个变体是更可取的,因为构造函数中的字段初始化通常使用构造函数参数中的外部值。