结合类和方法参数化类型

时间:2012-07-25 08:25:02

标签: java generics

我有这样的界面:

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参数。但是,现在你有了我想要做的一般情况,是否有可能的解决方案,或者我总是不得不提交一个可调用的? (或者完全删除泛型并执行不安全的演员表)

1 个答案:

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