Combine a class and a method of a parameterized type

I have an interface like this:

public interface BatchSynchronisedPool<R extends Runnable> { void execute(R runnable, Object batchIdentifier); public <T> Future<T> submit(Callable<T> callable, Object batchIdentifier); } 

I want to infer the upper bound for Callable, but still want to be able to support the <T> argument in the method:

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

Obviously, this does not work, because type C , which I will indicate, can only accept a specific range of T arguments. However, now you have in common what I'm trying to do, is there a possible solution, or do I always adhere to sending called ones? (Or even delete shared files and perform unsafe actions)

+4
source share
1 answer

I am not 100% sure, but I don’t think you can do what you are trying to do here. Since C not generic, you cannot use C<T> . Lots of code below, but tl; dr select option 3 . All that really changes at the end is how many BatchSynchronisedPool objects you need to create, which is not really a significant overhead ...


1. Save the parameter of type <T> general type in the method, send Callable<T> and check the runtime of the types , for example, your original solution, in the class that implements this interface.

 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. Save the parameter of type <T> general type in the method, send C and perform the cast , as you said, in the class that implements this interface.

 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. Create a new BatchSynchronisedPool for each type of T that you are trying to send, specifying T as the generic type parameter for the class. Then, every time you want to call submit for a different type, you need to create a new instance of 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); } } 
+4
source

All Articles