Let's say there's a framework type Row
with multiple type parameters, and a method that works with instances of the Row
type and uses all these type parameters.
I have a method that works with any type of Row
, even different types at the same time, so obviously I'm using the wildcard type Row<?,?>
. The question is, how do I invoke a method that takes a Row<R,K>
with a Row<?,?>
?
My line of thought: I don't exactly know what type Row<?,?>
is, but it's surely some kind of Row
alright. And when a generic method takes Row<R,K>
it means that it wants to do something with R
and K
but otherwise it can deal with any type of Row
. So my "any" type should work with a method that takes "any" type, right?
I'm attaching sample code below with things that I tried. The weirdest thing is that the very last line actually works, but it's not any more type safe than anything else I think. So basically I'd like a cleaner solution than this if possible or an explanation why this is the way to go.
package foo;
public class Experiment {
// Defined by a framework.
interface Key<K extends Key<K>> {}
interface Row<R extends Row<R, K>, K extends Key<K>> {}
static <R extends Row<R, K>, K extends Key<K>> R copyRow(R row) {
return row;
}
// My experiments below.
static class Wrapper<R extends Row<R, K>, K extends Key<K>> {
public final R row = null; // fixme
public final Class<R> clazz = null; // fixme
}
static <R extends Row<R, K>, K extends Key<K>> R upcast(Row<?, ?> row) {
return (R) row;
}
static <R extends Row<R, K>, K extends Key<K>> R upcast(Row<?, ?> row, Class<R> clazz) {
assert row.getClass().equals(clazz);
return (R) row;
}
public static void main(String[] args) {
Wrapper<?, ?> wr = null; // fixme
copyRow(wr.row); // Compilation error
copyRow(upcast(wr.row)); // Compilation error
copyRow(upcast(wr.row, wr.clazz)); // This works, why?
}
}
(You can send this sample straight to javac to see what happens. With Java 1.8: https://pastebin.com/LB10ySsD)