以下两个之间有什么区别,哪个更好?
public class foo {
int i = 2;
}
public class foo {
int i;
foo() {
i = 2;
}
}
答案 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)
特别是在这种情况下,这两种变体没有区别。第一个变体是更可取的,因为构造函数中的字段初始化通常使用构造函数参数中的外部值。