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
MyList
instance whereT
isDouble
. That’s OK: theDouble
class implements theNumber
interface.The
items
has a notional type ofList<Double>
and we initialize it with anArrayList
. So we now have a list what should only containDouble
values.In the call to
func
we attempt to add anInteger
to 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.