Add elements to a List<? extends Number>

Asked

Viewed 167 times

4

Why it is not possible to add elements to a list of type List<? extends Number>?

for example :

public class GenClass{
  public static void main(String args[]){
    List<? extends Number> ml=new Vector<Integer>();

    ml.get(0); //ok
    ml.add(new Integer(7)); // erro de compilação
    ml.add(new Double(7d));// erro de compilação
    ml.add(new Number(7));// erro de compilação
    ml.add(new Object());// erro de compilação
  }
}
  • Now I understand what is covariance and contravariance. I just don’t understand why it gives compilation error when I try to add a type that extends Number.

  • I didn’t get that either, ml.get(0) returns a Number, but when I tested do ml.add(ml.get(0)); also gave compilation error! After all, what kind of objects a list "List<? extends Number>" is able to receive? You can help us @Articuno? :) - Obs.: when doing List<Number> ml = new Vector<Number>(); (unused extends) the list can receive Integer and Double normally.

  • 1

    Number is an abstract class representing a collection of types, you cannot define a list that accepts number types and on the right hand side define the vector for integer type, there is no way List ensures that the number type is integer, since number is an inherited supertype of several numeric subtypes like Double, Float. This list becomes read only, it is not possible to add anything as it is not possible to guarantee that the type of number adding is the same informed in the assignment

  • What if I make a list? extends Number> ml=new Vector<Number>(); Why can’t I also add its subtypes, giving compilation error? but when I do List<? super Number> ml=new Vector<Number>(); I can add Double Integer, etc.?

  • My explanation in the previous comment is valid for all cases where you use List<? extends Number> regardless of what you declare on the right side.

  • What the compiler takes into account is the reference variable.

  • If you stop to notice, the problem that occurs in List<? super Number> is exactly the opposite that occurs with List<? extends Number>, Because the problem here is the exact opposite of what I explained. Once again reinforcement: you need to read all the answers of the two links and understand the concept of covariance and contravariance to understand this problem.

  • @I would if I did "List<? extends Number> ml = new Vector<Integer>();" and then did "ml.add(new Double(7d));" I would expect to receive a Classcastexception at runtime, but from what I understood from what you said, the Compiler will not allow me to add anything to the "ml" list to avoid this type of Exception. That means that at no time will the Compiler allow me to do "ml.add(...)"?, there is absolutely nothing I can pass as parameter that the compiler accepts?

  • @Douglas, you see, who defines the type is the statement on the left. So, this statement says that we will create a list that accepts only subtypes of Number, it limits only what we start on the left side and not what we will add to the created list. When adding something to this list, there is no way to guarantee that that object is allowed in the list, because a Double would be a type allowed in that list because it inherits from Number, but the compiler has no way to verify that the list does not allow Double, so it does not allow the addition.

  • I modified the question so that it is no longer duplicate and more specific the doubt, see if it is ok, anything wrong, let me know to undo the editing.

  • @Tiagos I disagree with this being duplicate. The other question talks about the ? super and not about the ? extends. The answer even talks a little about the ? extends, but does not go into more detail and does not talk about the problem outlined in this question.

Show 7 more comments

1 answer

7


Adding elements to this type of list is not possible as the wildcard declaration of List<? extends Number> ml means that the variable ml may contain any family value Number, instead of any value of a specific type. See the equivalent assignments below that would be allowed:

List<? extends Number> foo3 = new ArrayList<Number>;  // Number "extends" Number
List<? extends Number> foo3 = new ArrayList<Integer>; // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>;  // Double extends Number

That said, the type of object you can add to the List foo3 which would be valid after any of the above ArrayList would bump into the problems below:

  • You can’t add one Integerbecause foo3 could be pointing to a List<Double>.
  • You can’t add one Doublebecause foo3 could be pointing to a List<Integer>.
  • You can’t add one Numberbecause foo3 could be pointing to a List<Integer>.

Therefore:

You cannot add any object to List<? extends T> because you can’t guarantee that List is actually pointing to this type, so you cannot guarantee that the object to be added is allowed in that list. The only "guarantee" you have is that you can only read this list and you will get one T subclass of T.

The reverse logic applies to the use of super, according to the assignments below, which are also valid:

List<? super Number> foo3 = new ArrayList<Number>; // Number é "superclasse" de Number
List<? super Number> foo3 = new ArrayList<Object>; // Object é "superclasse" de Number

About List<? super T>, the following conclusion can be reached:

You can’t read the type T specific (for example Number) from List<? super T> because you can’t guarantee what kind of List is really pointing to it. The only "guarantee" you have is that you are able to add a type value T(or any subclass of T) without violating the integrity of the list being pointed out.

The statement to the left(List<? extends Number> foo3) sets the data type that can be assigned to your Arraylists on the right(= new ArrayList<Integer>();), and not the data type that can be added to the created list.

Translated and adapted from this reply from Soen


References for reading:

  • If I can’t add any object to List<? extends T> , what’s the purpose of creating it?

  • @user2509556 on the link of the answer I translated from Soen has this explanation, take a look at it. I just did not translate to not leave the initial focus of the question

Browser other questions tagged

You are not signed in. Login or sign up in order to post.