javagenericsbounded-wildcardbounded-types

Difference between Bounded Type parameter (T extends) and Upper Bound Wildcard (? extends)


I know that there was a similar question already posted, although I think mine is somewhat different...

Suppose you have two methods:

// Bounded type parameter
private static <T extends Number> void processList(List<T> someList) {

}

// Upper bound wildcard
private static void processList2(List<? extends Number> someList) {
    // ...
}

As far as I know, both methods accepts arguments, that are List of type Number or List of subtype of Number.

But what's the difference between the two methods after all?


Solution

  • There are several differences between the two syntaxes during compile time :

    • With the first syntax, you can add elements to someList but with the second, you can't. This is commonly known as PECS and less commonly known as the PUT and GET prinicple.
    • With the first syntax, you have a handle to the type parameter T so you can use it to do things such as define local variables within the method of type T, cast a reference to the type T, call methods that are available in the class represented by T, etc. But with the second syntax, you don't have a handle to the type so you can't do any of this.
    • The first method can actually be called from the second method to capture the wildcard. This is the most common way to capture a wildcard via a helper method.

      private static <T extends Number> void processList(List<T> someList) {
          T n = someList.get(0);
          someList.add(1,n); //addition allowed.   
      }
      
      private static void processList2(List<? extends Number> someList) {
          Number n = someList.get(0);
          //someList.add(1,n);//Compilation error. Addition not allowed.
          processList(someList);//Helper method for capturing the wildcard
      }
      

    Note that since generics are compile time sugar, these differences at a broader level are only limited to the compilation.