4

我有一个这样的界面:

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参数。但是,现在您对我正在尝试做的事情有了大致的了解,是否有可能的解决方案,或者我是否总是不得不提交一个可调用的?(或者完全删除泛型并执行不安全的强制转换)

4

1 回答 1

4

我不是 100% 确定,但不要认为你可以在这里做你想做的事情。由于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>方法上的泛型类型参数,提交 aC并执行强制转换,就像您建议的那样,在实现此接口的类中。

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);
     }
}

BatchSynchronisedPoolTT3. 通过指定为类的泛型类型参数,为您尝试提交的每种类型创建一个新类型。然后每次你想调用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);
     }
}
于 2012-07-25T09:40:56.110 回答