嘿,我在这里看到了这个话题:Can I call methods in constructor in Java?
我的问题是微笑,但有些不同。
如果我从A类的构造函数调用B之外的类,并使用A的this
,我想知道发生了什么。
在下面的示例中,A是JobImpl
,B是Scheduler中的队列。
class JobImpl implements Job
{
public JobImpl(Scheduler s, JobHandler runJob, boolean advancedWaitOnCancel, boolean oneShot)
{
this.s = s;
this.runJob = runJob;
this.advancedWaitOnCancel = advancedWaitOnCancel;
this.oneShot = oneShot;
jobReadyPhaser = advancedWaitOnCancel ? new AdvancedCountdownImpl(this) : new AdvancedCountdownNoOp();
this.s.jobs.add(this);
}
}
在我的示例中,我调用了两个外部方法/其他构造函数。
我调用AdvancedCountdownImpl(this)
的构造函数,并将this
添加到该类之外的队列中。
我将构造函数的输入参数分配给final字段。
在分配最后一个字段之前,我可以将this.s.jobs.add(this)
向上移动一点。没问题-从编译器的角度来看。
在那个链接的主题中,我看到可能存在继承问题。
在我的JobImpl类中,存在一些子类(不仅是在我的“接口”中,而且实际上是在JobImpl ^^中)
最有趣的是jobs.add(this)
。
可能是,在构造函数结束之前,另一个线程访问了该列表并对其内容进行处理。这样该线程可以访问该Job
并对其进行处理。
如果在jobs.add(this)
之后的那个构造器中,将this.s = s
移到该行的上方,则可能是未实例化其他最终字段。正确吗?
在那种情况下,我的程序会做什么-那么?
好吧,现在我将this.s.jobs.add(this)
放在该构造函数的末尾。所以我想最终字段将被实例化
还是不?也许编译器出于优化目的而交换行的内部?
好吧,如果编译器愿意这么做的话,那么我的JobImpl
就是ANY!另一个线程在队列中的访问时间完全实例化了?
或者在那种情况下我还会遇到继承问题吗?如果其他线程可以访问某些方法,谁被覆盖?
我不是应该将这些作业推到构造函数中的那个队列中,而是一步步地进行吗?那么,构造函数调用之后是init调用吗?
有更好的解决方案吗?
当我可以做到时,我做了什么? -将this
从构造函数推到外部?也许没有其他线程了?
我的jobReadyPhaser
也是最后一个字段。所以我必须在构造函数中构造那个AdvancedCountdownImpl(this)
。
但是我想我在这里100%安全,是因为AdvancedCountdownImpl
对此this
不做其他任何事情,而是将其保存到自己的字段中,以备后用。