I have this generic function:
public static <T extends Number> T sum(List<T> list){
Number tot = 0;
for(Number n: list){
tot = tot.doubleValue() + n.doubleValue();
}
return (T)tot;
}
Recall from the main with this code:
public static void main(String[] args) {
ArrayList<Integer> listInt = new ArrayList<>();
listInt.add(3);
listInt.add(5);
listInt.add(6);
listInt.add(8);
System.err.println("Sum: " + Calcolatrice.sum(listInt))
}
I therefore expect (being listInt an ArrayList of integers) that the value returned by the function sum is T = Integer and that in this case, give me a conversion error from Double to Integer. The type of the result is instead Double and no error is thrown. The cast (T)tot does not have the desired result.
I suppose it's because Java handles generics stance phase, but someone knows better explain why it works this way?
The Generics are only used at compilation to make sure you are not making mistakes in your code : Here, the parameter is List<T>
, and the receiving variable must be of type T
. That's all.
During runtime, T
doesn't exist, and tot
is a not an instance of T
; it's a Number
.
You can use T
inside your method to receive the undefined instances but, for example, you can't make a new T()
.
When you look at the type hierarchy you see that both Integer
and Double
are children of Number
: so they are siblings and you cannot directly cast Double
to Integer
:
Double testDbl = 3.14;
Integer testInt = (Integer)testDbl; // this will NOT compile
The compiler cannot know for sure, if the cast in the return statement of your sum
function will work or fail: but the compiler will show a warning:
Unchecked cast: 'java.lang.Number' to 'T'
Because of the hard-cast (T)tot
, the compiler will simply take it for granted that your function returns an Integer
(which it does not).
And finally, because of type erasure, there is no runtime check.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With