Skip to content
Advertisement

Unable to add value to a java generic list

Here’s my sample code:

public class MyList<T extends Number> {

  private List<T> items;

  public void func() {
    items.add(Integer.valueOf(1));
  }
}

I think I should be able to add integer to items, but compilation fails:

Required type: T
Provided: Integer

Anyone knows what’s wrong here?

Advertisement

Answer

Let us consider a more complete version of your example:

public class MyList<T extends Number> {

    private List<T> items = new ArrayList<>();

    public void func() {
        items.add(Integer.valueOf(1));
    }
}

Suppose for the sake of argument that the compiler says that is OK.

And now we will create an instance and call the func method:

MyList<Double> myDoubles = new MyList<>();
myDoubles.func();

Here is what happens.

  1. We create a MyList instance where T is Double. That’s OK: the Double class implements the Number interface.

  2. The items has a notional type of List<Double> and we initialize it with an ArrayList. So we now have a list what should only contain Double values.

  3. In the call to func we attempt to add an Integer to the List<Double>. That is wrong!

That is what the compilation error is saying with the Required type: T Provided: Integer message.

To spell it out, the compiler expects a value whose type is the type that T is going to be at runtime. But you have given it Integer. While Integer implements the Number interface, it is not necessary the same as what T will be at runtime. That is the root cause of your compilation error.


So what is the solution?

Well it depends on what the (actual) problem that this example is intended to solve. If you want item to be able to hold any Number, you should change

 private List<T> items = new ArrayList<>();

to

 private List<Number> items = new ArrayList<>();

and items.add(Integer.valueOf(1)) should work.

On the other hand, if you want to add 1 to items as an instance of the runtime type of T, that is much more difficult. The problem is that the code of MyList (as written) does not and cannot know what that type is! So, you need to EITHER pass the T instance representing 1 as a parameter to func OR pass a Class<T> parameter to func or the constructor and use reflection to create the instance of that class to represent 1.

But if you want something to auto-magically convert the Integer to what ever the actual runtime type of T is … that is not possible.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement