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.
We create a
MyListinstance whereTisDouble. That’s OK: theDoubleclass implements theNumberinterface.The
itemshas a notional type ofList<Double>and we initialize it with anArrayList. So we now have a list what should only containDoublevalues.In the call to
funcwe attempt to add anIntegerto theList<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.