As per my understanding the following generic function in java:
public static <T> T f(T x) {
Integer[] arr = new Integer[4];
T ret = (T) arr[2];
return ret;
}
is compiled to the following form (as it is unbounded):
public static Object f(Object x) {
Integer[] arr = new Integer[4];
Object ret = (Object) arr[2];
return ret;
}
However, when I run the following statement, the compiler is able to figure out the return value to be Integer type. How does the compiler figure it out?
Integer i = f(new Integer(4));
Shouldn’t the function be written as following for the above statement to work?
public static <T extends Integer> T f(T x) {
Integer[] arr = new Integer[4];
T ret = (T) arr[2];
return ret;
}
Generics use type erasure. That basically means that generics are nothing more than implicit casts so when you do:
it’s no different to a normal
Listand may containIntegers or anything really. You’re just telling Java to castget()to anInteger(and other things). The type simply isn’t retained at runtime (mostly).Arrays are different. Arrays are what’s called covariant. That means their type is retained at runtime. So you can do:
which is perfectly legal and will compile and run. But:
But it gets more subtle than that too.
As to your function. When you write:
you’re telling the compiler to derive
T, being the argument type and the return type, from the argument. So when you pass in anIntegerthe return type isInteger. When you call:the compiler is simply following your instructions. The function does take and return an
Objectin compiled form but it just does this:implicitly.
Just like the
Listexample above there is nothing stopping you havef()return anything you like rather than what it’s supposed to return based on the parameterized type.