我在正常情况下理解这个警告,如:
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()。即使在子类准备好构造后很长时间执行回调的情况下,这仍然是危险/风险吗?
答案 0 :(得分:2)
即使在子类准备好构造后很长时间执行回调的情况下,这仍然是不好/有风险的
是的,它仍有风险。构造函数调用不原子,所以如果你在另一个线程中执行它,从构造函数中推迟实例方法的调用就不会那么安全,因为你无法保证在(最终)调用了线程。
现在, 假设 ,如果子类对象是完全构造的(强调if),那么是的,未来的回调将是安全的。换句话说,它不会绕过部分构造的对象,这个对象在访问它时非常危险。
答案 1 :(得分:1)
我会说是的,因为在完全构造之前将Test
对象暴露给第二个线程,这是有风险的。
如果需要通过确保调用Test
来控制hello
实例的初始化,请考虑使用工厂方法进行实例化。将其与私有构造函数相结合,您可以保证在所有hello
个对象上安全地调用Test
:
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() {
}
}