1

Please, consider the Test Java class below.

Why does test2() method compile successfully, but test1() doesn't?

import java.util.Arrays;
import java.util.List;

public class Test {

    public <N extends Number> List<N> test1(){
        //compile error: Type mismatch: cannot convert from List<Integer> to List<N>
        return Arrays.asList(1,2,3);
    }

    public List<? extends Number> test2(){
        //no compile error
        return Arrays.asList(1,2,3);
    }

}
jair.jr
  • 597
  • 1
  • 7
  • 13
  • 2
    Does https://stackoverflow.com/questions/897935/when-do-java-generics-require-extends-t-instead-of-t-and-is-there-any-down help? – GhostCat Dec 04 '18 at 14:14
  • 1
    https://stackoverflow.com/questions/30498190/is-listdouble-a-subtype-of-list-extends-number-and-why – xingbin Dec 04 '18 at 14:19
  • As an aside: `N` is a type parameter that exists only in an output. Thus it is basically a free cast that the caller gets to determine contextually. That's generally a bad design: since the caller can make `N` be whatever type it wants, how can the function return the right type? (There are specific cases where this is correct, like `Collections.emptyList()`, but they're rare.) – Daniel Pryden Dec 04 '18 at 14:23

1 Answers1

2

It will become clearer if you write the code that calls these methods.

For example:

public static void main (String args) {
    Test obj = new Test();
    List<Double> list1 = obj.test1 ();
    List<? extends Number> list2 = obj.test2 ();
}

As you can see, the output of test1() can be assigned to a List<Double>, which means it cannot return a List<Integer>.

On the other hand, the output of test2() can be assigned only to a List<? extends Number> or a List<? extends Object> or a List<?>, and a List<Integer> can be assigned to all three.

Eran
  • 387,369
  • 54
  • 702
  • 768