I am trying to understand the usage of lower bound wildcards in some depth. I am trying to write a generic method copy which copies the contents of one List to another. I came up with this method signature:
<T> void copy(List<T> dest, List<? extends T> src)
I think this signature is comprehensive to address all scenarios. However, I see that in the Java Collections class the method signature is like this:
<T> void copy(List<? super T> dest, List<? extends T> src)
I do not understand why they use List<? super T> dest instead of just List<T> dest. Is there some extra flexibility with their signature?
There is no practical difference without explicit type witnesses.
Without specifying a type witness as done by Eran, there are no differences in flexibility between the two methods.
Essentially, the use of ? super T over T is only a stylistic difference, however it is better practice, as can be seen by applying a number of principles of good code:
? super T more explicitly shows what types dest should take.src at all to know what types dest can take.extends while a consumer parameter ("out" below) should use the super keyword.Using ? super T is also recommended by the Java tutorials (they even use a copy function):
For purposes of this discussion, it is helpful to think of variables as providing one of two functions:
An "In" Variable
An "in" variable serves up data to the code. Imagine acopymethod with two arguments:copy(src, dest). Thesrcargument provides the data to be copied, so it is the "in" parameter.An "Out" Variable
An "out" variable holds data for use elsewhere. In thecopyexample,copy(src, dest), thedestargument accepts data, so it is the "out" parameter.You can use the "in" and "out" principle when deciding whether to use a wildcard and what type of wildcard is appropriate. The following list provides the guidelines to follow:
Wildcard Guidelines:
- An "in" variable is defined with an upper bounded wildcard, using the
 extendskeyword.- An "out" variable is defined with a lower bounded wildcard, using the
 superkeyword.
Here's an example:
The following snippet passes compilation with the signature <T> void copy(List<? super T> dest, List<? extends T> src) but doesn't work with the signature <T> void copy(List<T> dest, List<? extends T> src):
YourClass obj = new YourClass ();
List<HashMap<String,String>> lhm = new ArrayList<>();
List<Map<String,String>> lm = new ArrayList<>();
obj.<HashMap<String,String>>copy (lm,lhm);
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With