"? extends ParentClass" does read only?

In the following Java code, I created a nums list. I can assign a different list during the announcement. But new elements cannot be added except null . So, does that mean nums read-only? Why? Can I add new items to this 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 went through this link. I can not get the exact reason.

+6
source share
4 answers

Can I add new items to this list?

No ... because this code does not know that it is a "really" list. 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 do you use a wildcard, for example ? extends T ? extends T , you can only get values ​​through the API ... and when do you use a wildcard, for example ? super T ? super T , you can only enter values ​​through the API, because that is safe.

+5
source

No, this is not just for reading ... although this is the intention.

Given a List<? extends Number> List<? extends Number> , the compiler converts its type to List<X> , where X is an unknown subtype of Number. Therefore, the object has an add(X) method. We can call a method with argument X ... for example, null .

And since get() returns X , we can also call add() with a value from get() .... Directly calling list.add(list.get(i)) will fail, although that makes sense. We need a little helper .

Classic example: Collections.reverse(List<? extends Object> list) . This method will change the list , despite the wildcard.

You can also call mutating methods such as clear() , of course, on any list.


In this case, the wildcard is mainly intended for use by variance , and most often it conveys the intent of the API developer on whether the type parameter is intended for input or output. For example, declaring List<? super/extends Foo> List<? super/extends Foo> , the API expresses that it intends to enter T in or get T from the list.

This is a misconception that wildcard does read / write only. But this misconception works in most use cases. And the more people have this error, the more it becomes a convention ...

see my article on the template - http://bayou.io/draft/Capturing_Wildcards.html

+2
source

Does this help when you think of List<? extends Number> nums List<? extends Number> nums as a List the type of thing that extends Number , but you cannot be sure of what. Thus, everything you do with nums should be able to do this.

Adding null works because null can be distinguished absolutely. Everything else that you are trying to add will fail, because the compiler cannot be 100% sure that the thing you are adding expands the list from which the list is made.

Instead of List<? extends Number> nums List<? extends Number> nums do List<Number> nums , because you can still insert anything that extends Number .

? does not mean "nothing", it is closer to the meaning of "some specific but unknown."

0
source

Generics are compilation time.

So, the compiler will decide what the actual type is, which we will use.

 List<? extends Number> 

This means that we are not sure what the actual type of the object is.

So, the compiler will not make sure what the actual type is in the list.

-1
source

All Articles