1

我在正常情况下理解此警告,例如:

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() 的调用不会立即发生。即使在子类准备好构造后很长时间执行回调的情况下,这仍然很糟糕/有风险吗?

4

2 回答 2

2

即使在子类准备好构造后很长时间执行回调的情况下,这仍然很糟糕/有风险吗

是的,它仍然有风险。构造函数调用不是原子的,因此如果您在另一个线程中执行此操作,则推迟从构造函数调用实例方法同样安全,因为您无法保证在(最终)调用线程时对象将被完全构造。

现在,假设,如果子类对象完全构造(强调 if),那么是的,未来的回调将是安全的。换句话说,它不会绕过部分构造的对象,与其访问它一样危险。

于 2013-04-22T12:13:49.673 回答
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() {
    }
}
于 2013-04-22T12:16:55.393 回答