构造函数调用可重写方法(延迟调用)



我理解这个警告在正常情况下,如:

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() {
    }
}

最新更新