Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return type of generic method (Java)

Tags:

java

generics

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?

like image 266
Gabriele Picco Avatar asked Mar 04 '17 09:03

Gabriele Picco


2 Answers

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().

like image 125
Guillaume F. Avatar answered Sep 28 '22 01:09

Guillaume F.


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.

like image 41
TmTron Avatar answered Sep 28 '22 00:09

TmTron