我理解这个警告在正常情况下,如:
class Test {
public Test() {
hello();
}
public void hello() {}
}
但是如果我们有这样的东西呢:
class Test {
public Test() {
// Put the call on a queue that will be executed later
queue.submit( new Runnable() {
public void run() {
hello();
}
});
}
public void hello() {}
}
,其中对hello()的调用不会立即发生。这仍然是坏的/有风险的情况下,即使回调执行后很长时间的子类准备构造?
即使在子类构造好很久之后回调执行的情况下,这仍然是坏的/有风险的吗?
是的,它仍然有风险。构造函数调用是而不是原子性的,因此,如果在另一个线程中延迟调用实例方法,从构造函数中延迟调用实例方法的安全性不会降低,因为您无法保证在(最终)调用线程时将完全构造对象。
现在,假设,如果子类对象被完全构造(强调if),那么是的,未来的回调将是安全的。换句话说,传递部分构造的对象并不像访问它那么危险。
我会说,是的,这是有风险的,因为你在Test
对象完全构造之前将其暴露给第二个线程。
如果您需要通过确保hello
被调用来控制Test
实例的初始化,请考虑使用工厂方法进行实例化。将它与私有构造函数结合起来,您可以保证在所有Test
对象上安全地调用hello
:
public Test {
/**
* Factory method to create Test instances and safely call public method
*/
public static Test getInstance() {
Test test = new Test();
test.hello();
return test;
}
/**
* Private constructor to control Test object creation.
*/
private Test() {
super();
}
public void hello() {
}
}