喜欢这样吗?
abstract public class BaseTask extends Runnable {
public BaseTask(ParamA aParam) {
// do something with aParam
StaticExecutorService.submit(this);
}
}
public class AbcTask extends BaseTask {
public ABC(ParamA aParam, ParamB bParam) {
super(aParam);
}
@Override
public void run() {
}
}
然后可以通过执行
来创建类并排队等待执行new AbcTask();
我不确定这是否可以,因为当ExecutorService
决定执行AbcTask
时,它仍在构建?
如果您出于任何原因不建议这样做,请说明并详细说明。
由于
答案 0 :(得分:2)
这可能有用(至少,我对Java不太熟悉,不知道为什么它不会),但我不推荐它,因为它引入了太强大的耦合:AbcTask
将与StaticExecutorService
并且可以重复使用,而不是那么容易。这也将使AbcTask
更难以测试和调试。
此外,您通过将提交文件折叠到执行程序中来“重载”对象构造的含义。如果您以后决定要在构建它们并提交它们之间对AbcTask
个对象做些什么,该怎么办?
答案 1 :(得分:1)
在构造函数完成之前,我们不应该使用this
。
对象在完成它的c'tor后完全实例化。因此,StaticExecutorService
内传递的对象可能无法完全创建,可能无法使用。
我不知道规范是否支持我的上述陈述。但我感觉如此。
因此,acc。对我来说应该避免。
答案 2 :(得分:1)
在Effective Java中,Joshua Bloch解释了为什么从构造函数调用protected / public方法不是一个好习惯。参见第2版,CH-4:构造函数不得调用可覆盖的方法,直接或间接。
StaticExecutorService.submit(this);
上面的行将从构造函数中调用公共方法run
,这是不期望的。
书中的解释:构造函数不得调用可覆盖的方法,直接或间接
如果违反此规则,将导致程序失败。超类构造函数运行 在子类构造函数之前,所以子类中的重写方法将得到 在子类构造函数运行之前调用。如果重写方法取决于 在子类构造函数执行的任何初始化上,该方法都不会 表现得像预期的那样。
答案 3 :(得分:0)
在您的示例中,它可能会工作但是,因为对super()
的调用必须是BaseTask
子类中的第一个,这意味着构造函数不会是能够在提交任务之前执行任何操作。
从您的示例中,无法使用第二个参数,因为在将任务分配给属性之前将提交任务。
如果我们考虑以下代码:
public class MyTask extends BaseTask {
public ABC(ParamA aParam, String name) {
super(aParam);
this.name = name == null ? "Default Value" : name;
}
@Override
public void run() {
System.out.println("Name length: "+ name.length());
}
}
由于run()
可以在分配this.name
之前调用,System.out
行可以NullPointerException