I'm assuming your Operation classes and interfaces look something like this:
interface IOperation<T> {
public List<T> processList(List<T> list);
public List<T> getList();
}
interface ITotallyDifferentOperation<T> {
public List<T> processList(List<T> list);
public List<T> getList();
}
class MyOperation<T> implements IOperation<T> {
public List<T> processList(List<T> list) {return null;}
public List<T> getList() {return null;}
}
class MyTotallyDifferentOperation<T> implements ITotallyDifferentOperation<T> {
public List<T> processList(List<T> list) {return null;}
public List<T> getList() {return null;}
}
And that the error you get is something like this:
void myMethod(final IOperation<?> parameter1,
final ITotallyDifferentOperation<?> parameter2) {
// COMPILE ERROR: processList() is not applicable for the arguments
parameter1.processList(parameter2.getList());
}
The reason for this compile error is that myMethod() allows the type of parameter1 and parameter2 to be different from each other.
The best option (In my opinion) would be to not wildcard parameter1 and parameter2, and instead ensure that they are the same generic type, like so:
Operation<T> parameter1 = null;
ITotallyDifferentOperation<T> parameter2 = null;
Based on the IOperation interfaces any of these operations would require myMethod() to accept two parameters with the same generic types, like so:
void <T> myMethod(
final IOperation<T> operation,
final ITotallyDifferentOperation<T> totallyDifferentOperation) {
operation.processList(totallyDifferentOperation.getList());
}
BUT
If you don't want to do any of the above, then you could change both IOperation interfaces processList methods to accept wildcards so that you can leave all the inputs as wildcards, like so:
interface IOperation<T> {
public List<T> processList(List<?> list);
public List<T> getList();
}
interface ITotallyDifferentOperation<T> {
public List<T> processList(List<?> list);
public List<T> getList();
}
The only issue then is that you wont have any compile-time type guarantee within those methods and you'd have to check them at run-time...
EDIT in response to Malte Hartwig:
Not wildcarding the parameters will not compile, as T cannot be resolved. That's the whole problem: you do not know which type it is
You don't need to know what type it is, just that they are the same type T. I have expanded on my answer here:
// remove wildcards, use a generic method, rather than deciding Type in a switch statment.
<T> void someMethod(final Class<T> klass, final int DB_OPERATION_TYPE) {
IOperation<T> parameter1 = new MyOperation<T>();
ITotallyDifferentOperation<T> parameter2 = new MyTotallyDifferentOperation<T>();
// ... OR ...
<T> void someMethod(final int DB_OPERATION_TYPE, IOperation<T> parameter1,
ITotallyDifferentOperation<T> parameter2) {
// ... Other conditions to evaluate before calling the myMethod ...
switch(DB_OPERATION_TYPE) {
case 1:
myMethod(parameter1, parameter2);
break;
case 2:
myOtherMethod(parameter1, parameter2);
break;
}
}
<T> void myMethod(final IOperation<T> operation, final ITotallyDifferentOperation<T> totallyDifferentOperation) {
operation.processList(totallyDifferentOperation.getList());
}
<T> void myOtherMethod(final IOperation<T> operation, final ITotallyDifferentOperation<T> totallyDifferentOperation) {
// something... ?
}
And to call this method:
final int DB_OPERATION_TYPE = 1;
someMethod(String.class, DB_OPERATION_TYPE);
// OR
someMethod(DB_OPERATION_TYPE, new MyOperation<String>(), MyTotallyDifferentOperation<String>());
As for bringing the method call into the switch and ditching the parameters altogether: Op clarified that this is not an option.
Op clarified this in response to you only after my answer had been posted. I have now edited it out of my answer.