简体   繁体   English

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

[英]Constructor Calls Overridable Method (delayed call)

I understand this warning in the normal case like: 我在正常情况下理解这个警告,例如:

class Test {
  public Test() {
    hello();
  }
  public void hello() {}
}

but what if we have something like: 但如果我们有类似的东西呢:

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

where the call to hello() will not happen immediately. 其中对hello()的调用不会立即发生。 Is this still bad/risky even in the case where the callback executes long after the subclass is ready constructed ? 即使在子类准备好构建后很长时间执行回调的情况下,这仍然是不好/有风险的吗?

Is this still bad/risky even in the case where the callback executes long after the subclass is ready constructed 即使在子类准备好构造之后很长时间执行回调的情况下,这仍然是不好/有风险的

Yes, its still risky. 是的,它仍然存在风险。 Constructor invocation is not atomic, so deferring the invocation of an instance method from the constructor is no less safe if you do it in another thread, since you have no guarantee that the object will be fully constructed when the thread is (eventually) invoked. 构造函数调用不是原子的,因此如果在另一个线程中执行它,则从构造函数中推迟实例方法的调用也同样安全,因为您无法保证在(最终)调用线程时将完全构造该对象。

Now, hypothetically , if the subclass object is fully constructed (emphasis on if), then yes, the future callback will be safe. 现在, 假设 ,如果子类对象是完全构造的(强调if),那么是的,未来的回调将是安全的。 In other words, its not passing around the partially constructed object that is dangerous so much as its accessing it. 换句话说,它不会绕过部分构造的对象,因为它访问它是危险的。

I would say yes it is risky just because you are exposing the Test object to a second thread before it is fully constructed. 我会说是的,因为你在完全构造之前将Test对象暴露给第二个线程是有风险的。

If you need to control the initialization of Test instances by insuring hello is called, consider using a factory method for instantiation. 如果需要通过确保调用hello来控制Test实例的初始化,请考虑使用工厂方法进行实例化。 Combine that with a private constructor and you can guarantee hello is safely called on all Test objects: 将它与私有构造函数结合使用,您可以保证在所有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() {
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM