Just
public final class Listener implements Worker<Runnable> { private Listener() {} @Override public void start(Class<? extends Runnable> taskClass) { ... } }
it is clear that any Thread subclass can accept a listener instance.
Worker<Runnable> worker = Listener.getInstance(); worker.start( MyThread.class );
If you want to restrict the type to clarify what works for Thread subclasses, you cannot
Worker<Thread> worker = Listener.getInstance();
but you can
Worker<? super Thread> worker = Listener.getInstance(); worker.start( MyThread.class ); // works for all Thread subclasses. worker.start( SomeRunnable.class ); // error; only for Thread subclasses.
If we hate wildcards (we do), we can argue that it is clear that Worker<Runnable> also a Worker<Thread> ; error[1] is just a dumb restriction.
One of the advantages of erasing is that we can establish such covariance.
@SuppressWarnings("unchecked") Worker<Thread> worker = (Worker<Thread>)(Worker) Listener.getInstance();
We know that casting is safe for all purposes and purposes.
If this is often necessary, we can move covariance casting to getInstance() for convenience:
Worker<Thread> worker = Listener.getInstance(); public final class Listener implements Worker<Runnable> static Listener instance = new Listener();
source share