构造函数调用可覆盖方法(延迟调用)

时间:2013-04-22 12:04:23

标签: java constructor callback override

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

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()。即使在子类准备好构造后很长时间执行回调的情况下,这仍然是危险/风险吗?

2 个答案:

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