Common Method Return Type (Java)

I have this general 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 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)) } 

So I expect (being a listInt ArrayList of integers) that the value returned by the sum of the function is T = Integer, in which case give me a conversion error from Double to Integer. The result type is instead of Double, and an error does not occur. Point cast (T) does not have the desired result.

I suppose because Java handles the static phase of generics, but does anyone know it is better to explain why it works this way?

+6
source share
3 answers

The return type Calcolatrice.sum(listInt) is actually an Integer thanks to the casting at the end of sum in your example. However, the actual result type is Double . Obviously, this is not a good situation, but this happened because you explicitly told the compiler in the role that the return value will be of the same type as the return value.

This situation means that if you write Calcolatrice.sum(listInt).toString() instead, you will get a ClassCastException: java.lang.Double cannot be cast to java.lang.Integer because you will call Integer.toString() on Double . In fact, your code runs System.out.println("Sum: "+ String.valueOf(Calcolatrice.sum(listInt))) , which works because it empties to Object (thus resolving the conflict) before calling toString .

As @TmTron points out, you cannot use types between Double and Integer in a box in the same way you can do with primitives.

i.e.

 int i = (int) 2.0; 

follows various rules:

 Integer i = (Integer) new Double(2.0) 
+1
source

Generalizations are used only for compilation, to make sure that you are not mistaken in your code: here the List<T> parameter, and the receiving variable must be of type T It's all.

At run time, T does not exist, and tot not an instance of T ; this is a Number .

You can use T inside your method to get undefined instances, but, for example, you cannot make new T() .

+3
source

When you look at the type hierarchy, you see that both Integer and Double are children of Number : therefore 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 whether the work or failure can be performed in the return statement of your sum function, but the compiler will show a warning:

 Unchecked cast: 'java.lang.Number' to 'T' 

Due to hard casting (T)tot compiler will simply take for granted that your function returns Integer (which is not the case).

And finally, due to the erasure type, the execution check is not performed.

+3
source

Source: https://habr.com/ru/post/1015469/


All Articles