Reputation:
Like so?
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() {
}
}
The class can then just be created and queued for execution by doing a
new AbcTask();
I'm not sure if this is ok because maybe it is still being constructed when ExecutorService
decides to execute AbcTask
?
If you don't recommend this for whatever reason, please state and elaborate.
Thanks
Upvotes: 3
Views: 338
Reputation: 8261
In Effective Java, Joshua Bloch explained why it is not a good practice to invoke a protected/public method from a constructor. See 2nd edition, CH-4: Constructors must not invoke overridable methods, directly or indirectly.
StaticExecutorService.submit(this);
Above line will invoke the public method run
from the constructor, and this is not expected.
Explanation from the book: Constructors must not invoke overridable methods, directly or indirectly
If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will get invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.
Upvotes: 1
Reputation: 7778
In your example it will probably work but as the call to super()
has to be the first in child classes of BaseTask
this means that the constructor won't be able to perform any operation before the submission of the task.
From you sample, the second parameter cannot be used since the task will be submitted before you can assign it to an attribute.
If we consider the following code:
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());
}
}
Since run()
can be called before the assignment of this.name
the System.out
line can end in NullPointerException
Upvotes: 0
Reputation: 13872
We should not use this
until the constructor is completed.
An object is instantiated fully after completion of it's c'tor. so the object passed within StaticExecutorService
might not be created fully and may not be usable.
I don't know if specification supports my above statement. but i feel so.
Hence, acc. to me it should be avoided.
Upvotes: 1
Reputation: 363597
This might work (at least, I'm not familiar enough with Java to see why it wouldn't), but I would not recommend it as it introduces too strong a coupling: AbcTask
would be tied to StaticExecutorService
and would be less reusable than it could easily be. This will also make the AbcTask
harder to test and debug.
Also, you're "overloading" the meaning of object construction by folding submission to an executor into it. What if, later on, you decide you want to do something to AbcTask
objects in between constructing them and submitting them?
Upvotes: 2