javagenericsgeneric-list

Generic methods tutorial


In https://docs.oracle.com/javase/tutorial/java/generics/upperBounded.html, it is suggested to implement a method

public static double sumOfList(List<? extends Number> list) {
    double s = 0.0;
    for (Number n : list)
        s += n.doubleValue();
    return s;
}

and then to invoce it with

List<Integer> li = Arrays.asList(1, 2, 3);
System.out.println("sum = " + sumOfList(li));
  1. Why is it illegal to put public static <T> double sumOfList(List<T extends Number> list) ?
  2. Is public static <T extends Number> double sumOfList(List<T> list) equivalent? If so, is it of less good style?
  3. When using the aforementioned code, why is it illegal to write System.out.println("sum = " + sumOfList<Integer>(li));?

Solution

    1. Why is it illegal to put

    Because that's just not the syntax.

    T is a type variable, the bounds have to be specified where the type variable is declared (within the <> preceding the method return type), not where it is used (in the same way that the type of a variable has to be specified where it is declared, not where it is used, e.g. String foo, not foo.<String>contains("a")).

    1. Is ... Equivalent?

    Not quite.

    The advantage of declaring a type variable and using that in the List<T> is that you can then declare variables of that type in the method.

    For example:

    T element = list.get(0);
    list.set(0, element);
    

    is not legal for a List<? extends Number>, but is for a List<T>.

    You can also do things like using T in the return type of the method and/or other parameters.

    But, if you don't need to do any of these things, you don't need a type variable, so don't declare one, just as you shouldn't declare variables you don't need.

    1. When using the aforementioned code, why is it illegal to write

    Because that's just not the syntax.

    However, you can write:

    System.out.println("sum = " + TheContainingClass.<Integer>sumOfList(li));
    

    (Or e.g. this.<Integer>sumOfList(...), if it were a non-static method)

    i.e. the <> comes before the method name, and the method invocation needs to be qualified.

    This <Integer> is sometimes called a "type witness", although that is not a term defined in the spec.