我有这样的界面:
public interface BatchSynchronisedPool<R extends Runnable> {
void execute(R runnable, Object batchIdentifier);
public <T> Future<T> submit(Callable<T> callable, Object batchIdentifier);
}
我想推断Callable的上限,但仍希望能够在方法上保留<T>
参数:
public interface BatchSynchronisedPool<R extends Runnable, C extends Callable> {
void execute(R runnable, Object batchIdentifier);
public <T> Future<T> submit(C<T> callable, Object batchIdentifier);
}
显然这不起作用,因为我指定的C
类型只能采用特定范围的T
参数。但是,现在你有了我想要做的一般情况,是否有可能的解决方案,或者我总是不得不提交一个可调用的? (或者完全删除泛型并执行不安全的演员表)
答案 0 :(得分:4)
我不是百分百肯定,但不要以为你可以做你想做的事情。由于C
不是通用的,因此您无法使用C<T>
。下面有很多代码,但是tl; dr 采取选项3 。到目前为止真正改变的是你需要创建多少个BatchSynchronisedPool
个对象,这实际上不是一个相当大的开销...
1。在方法上保留<T>
泛型类型参数,提交Callable<T>
并执行类型的运行时检查,例如您的原始解决方案,在实现此接口的类中。
public interface BatchSynchronisedPool<R extends Runnable> {
void execute(R runnable, Object batchIdentifier);
public <T> Future<T> submit(Callable<T> callable, Object batchIdentifier);
}
public class MyBSP<R, C> implements BatchSynchronisedPool<R, C> {
void execute(R runnable, Object batchIdentifier) { ... }
public <T> Future<T> submit(Callable<T> callable, Object batchIdentifier) {
// Check types.
if (!(callable instanceof MyDesiredCallableClass)) {
throw new IllegalArgumentException("Types don't match.");
}
// Do work.
T result = callable.call();
...
}
}
public class MyUsageClass {
public static void main(String[] args) {
// Submit string.
MyBSP<Runnable> bsp = new MyBSP<Runnable>();
bsp.submit(new StringCallable(), someObject1);
// Submit integer.
bsp.submit(new IntegerCallable(), someObject2);
}
}
2。保留方法上的<T>
泛型类型参数,提交C
并执行广告,就像您建议的那样,在实现此接口的类中。
public interface BatchSynchronisedPool<R extends Runnable, C extends Callable> {
void execute(R runnable, Object batchIdentifier);
public <T> Future<T> submit(Class<T> cls, C callable, Object batchIdentifier);
}
public class MyBSP<R, C> implements BatchSynchronisedPool<R, C> {
void execute(R runnable, Object batchIdentifier) { ... }
public <T> Future<T> submit(Class<T> cls, C callable, Object batchIdentifier) {
// Do work... with a cast.
T result = cls.cast(callable.call());
...
}
}
public class MyUsageClass {
public static void main(String[] args) {
// Submit string.
MyBSP<Runnable, Callable> bsp = new MyBSP<Runnable, Callable>();
bsp.submit(new StringCallable(), someObject1);
// Submit integer.
bsp.submit(new IntegerCallable(), someObject2);
}
}
第3。通过将BatchSynchronisedPool
指定为类的通用类型参数,为您尝试提交的每种类型T
创建新的T
。然后,每次要在其他类型上调用submit
时,您都需要生成BatchSynchronisedPool
的新实例。
public interface BatchSynchronisedPool<T, R extends Runnable, C extends Callable<T>> {
void execute(R runnable, Object batchIdentifier);
public Future<T> submit(C callable, Object batchIdentifier);
}
public class MyBSP<T, R, C> implements BatchSynchronisedPool<T, R, C> {
void execute(R runnable, Object batchIdentifier) { ... }
public Future<T> submit(C callable, Object batchIdentifier) {
// Do work. Types are okay; no checking or casting needed!
T result = callable.call();
...
}
}
public class MyUsageClass {
public static void main(String[] args) {
// Submit string.
MyBSP<String, Runnable, Callable<String>> stringBsp = new MyBSP<String, Runnable, Callable<String>>();
stringBsp.submit(new StringCallable(), someObject1);
// Submit integer.
MyBSP<Integer, Runnable, Callable<Integer>> integerBsp = new MyBSP<Integer, Runnable, Callable<Integer>>();
integerBsp.submit(new IntegerCallable(), someObject2);
}
}