I'd like to have a generic method that takes in an object of some type T, and also a Class representing that type. Eventually I plan to use this to create a Map<Class<?>, Object>, where I know that each class will map to an object of exactly its own type; I know I won't be able to convince the compiler of this, but I'd like to keep compile-time generic safety for as much of the code as I can. Here's a minimal example demonstrating the problem I'm running into:
public class Example {
public static <T extends Number> void foo(Class<T> c, T x) {
;
}
public static void bar(int x) {
foo(Integer.class, x);
}
public static void baz(Number x) {
foo(x.getClass(), x);
}
}
I can write the foo method with no problem, and it has the signature I want, and I can use it if I know exactly what types I have at compile time, as in bar, but I can't use it on objects of any type, as I try to in baz: baz does not compile, citing:
Example.java:11: error: method foo in class Example cannot be applied to given types;
foo(x.getClass(), x);
^
required: Class<T>,T
found: Class<CAP#1>,Number
reason: inferred type does not conform to lower bound(s)
inferred: CAP#1
lower bound(s): Number
where T is a type-variable:
T extends Number declared in method <T>foo(Class<T>,T)
where CAP#1 is a fresh type-variable:
CAP#1 extends Number from capture of ? extends Number
I think I understand the problem here: x.getClass() returns Class<? extends Number>, which establishes <? extends Number> as T, but x continues to have type Number, requiring T to be Number, thus the conflict. When I wrote this, I was hoping that the compiler would know that x.getClass() and x do share exactly the same T, but it makes sense that it can't know that.
So, what do I do here? Is there a way I can write something like foo and also something like baz? Should I abandon compile-time safety and do some casts at runtime? Is there a better way altogether to approach my end goal of Map<Class, Object>?