Given:
import java.util.*;
public class Hancock {
//insert code here
list.add("foo");
}
}
Which two code fragments, inserted independently at line 5, will compile without warnings? (Choose two)
A. public void addString(List list) {
B. public void addString(List<String> list) {
C. public void addString(List<? super String> list) {
D. public void addString(List<? extends String> list) {
Correct answers are B & C.
Answers A and B are quite clear for me. For the answers C & D i know which way the inheritence is going, however i cannot understand why answer D does not compile in Eclipse while all others do (A with warrning about generic, B & C without warrings).
Error in Eclipse for answer D is The method add(capture#1-of ? extends String) in the type List<capture#1-of ? extends String> is not applicable for the arguments (String)
.
On the other hand this compiles:
public void addString() {
List<? extends String> list1 = new ArrayList<String>();
List<? super String> list2 = new ArrayList<String>();
}
Why? Why <? super String>
does not compile in method declaration while it does compile in variable declaration.
I know that String
is final class and cannot be extended by any other class but that does not explain to me what is going on here.
First, let's see answer C:
public void addString(List<? super String> list) {
list.add("foo");
}
This method declaration says that you will be allowed to pass List
objects which are parametrized by some super class of String
, for example String
or Object
. So:
List<String>
the list.add("foo")
will be perfectly valid.List<Object>
the list.add("foo")
will be perfectly valid, because "foo" is a String
(and you can add a String
to a List<Object>
).This means that answer C is correct.
Lets now see answer D.
If you have a method declaration like this:
public void addString(List<? extends String> list) {
}
this means that you will be able to pass List
objects parametrized by some unknown subtype of String
. So, when you do list.add("foo");
the compiler won't be aware if the provided object has a type that matches the unknown subtype of String
and therefore raises a compile-time error.
When you have:
public void addString() {
List<? extends String> list1 = new ArrayList<String>();
List<? super String> list2 = new ArrayList<String>();
}
This fragment compiles fine, because list1
is defined to hold List
objects that are of some unknown subtype of String
, including the String
itself, which is why it's valid.
The problem is that you won't be able to add anything, except null
.
As for list2
, the variable can hold List
objects which are parametrized by some super-type of String
, including the String
itself.
More info:
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