我看到这个实例变量初始化的习惯用法很多
public class Test{
private Long l = 1l;
private MyClass mc = new MyClass();
public Test(){}
...
}
但我更喜欢
public class Test{
private Long l;
private MyClass mc;
public Test(){
l = 1l;
mc = new MyClass();
}
...
}
考虑到这些是非最终变量,在线程安全方面,2种方法是等价的还是比其他方法“更”正确?
答案 0 :(得分:6)
线程安全不是问题,因为这在构造阶段发生,并且两个线程不能构造相同的对象。好吧,如果你让this
从构造函数中逃脱,那么另一个线程可能在构造期间访问该对象,但你真的不应该这样做。功能方面,两个选项是相同的,所以即使存在线程安全问题,它们也会以同样的方式影响。
如果你需要进行一些无法在初始化程序中完成的计算,那么第一个在声明中初始化字段的选项并不总是可行的(即便如此,如果你这样做,你可以将初始化保留在构造函数之外)但是在初始化程序块中。但是,如果任何一种方式都可行,那么它纯粹是一种风格问题,我不认为Java程序员有明显的偏好,所以请选择对你来说更好的方式。
答案 1 :(得分:1)
由于您的变量是实例变量,而不是类变量,因此在初始化期间使用任一方法都没有线程安全问题。我敢肯定,如果有Java标准推荐的最佳实践,其他人也会参与进来。
答案 2 :(得分:1)
我认为这是个人偏好和项目编码标准的问题。
确保只在一个地方(构造函数或内联)初始化变量。
在构造函数中完成初始化工作可以为您提供更好的异常处理空间。
答案 3 :(得分:1)
它们都不是线程安全的。如果线程A构造对象,则线程B可能会或可能不会观察到未完全初始化的Test对象或MyClass对象。构造函数退出后的可见性保证仅适用于最终字段。
请参阅http://pveentjer.wordpress.com/2007/03/18/immutability-doesnt-guarantee-thread-safety/
答案 4 :(得分:0)
就线程安全而言,它们是等效的。两者都需要执行相同的指令,如果您更喜欢第二个(我根据您的喜好与您达成一致),那么我会使用它。如果您希望构造函数周围的线程安全,则需要围绕构造函数调用进行同步调用。
答案 5 :(得分:0)
我不确定是否早些回答。但是,我对以下情况有疑问:
我试图创建一个@Component类,其中有一个实例变量。现在,我想为每个请求创建一个实例变量的新对象。我不确定哪种方法是正确的?
--kubelet-extra-args --node-labels=alabel=foo,another=bar