In the following code Java, I have created a list nums
. I can assign the another list during the declaration. But new items cannot be added except the null
. So, does it mean the nums
is readonly? Why? Is it possible to add new items in that list?
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); //Generates error
nums.addAll(ints); //Generates error
nums.add(null); //works
System.out.println(nums.get(0)); //works
I have gone through this link. I can't get exact reason.
Is it possible to add new items in that list?
Nope... because that code doesn't know what it's "actually" a list of. Imagine if you could:
List<String> strings = new ArrayList<>();
List<? extends Object> objects = strings; // This is fine
objects.add(new Object()); // Fortunately this *isn't* valid...
System.out.println(strings.get(0).length()); // Or what would this do?
Basically, when you use a wildcard like ? extends T
you can only get values out via the API... and when you use a wildcard like ? super T
, you can only put the values in via the API - because that's what's safe.
No, it's not read-only... even though that is typically the intention.
Given a List<? extends Number>
object, the compiler converts its type to List<X>
where X is an unknown subtype of Number. Therefore, the object does have an add(X)
method. We can call the method with an X
argument... for example, null
.
And since get()
returns X
, we could also call add()
with a value from get()
.... Directly invoking list.add(list.get(i))
won't work, even though it makes sense. We will need a little helper.
The classic example is Collections.reverse(List<? extends Object> list)
. This method will modify the list
, despite the wildcard.
You can also call mutating methods like clear()
, of course, on any list.
That being said, wildcard is indeed mainly for use-site variance, and most often, it conveys the intention from the API designer of whether a type-parameter is intended for in or out. For example, by declaring List<? super/extends Foo>
, the API expresses that it intends to inject T in to, or, get T out of, the list.
It is a misconception that wildcard makes read/write-only. But this misconception works in most use cases. And the more people having this misconception, the more it becomes a convention...
see my article on wildcard - http://bayou.io/draft/Capturing_Wildcards.html
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