The typing of T
could be anything. Inside the class there is no way of knowing whether it's safe to put an Integer (int gets boxed here automatically) in the list or not. It's only safe to put a T
in a List<T>
.
There won't be a way to add a concrete object to a generic list. The list must have a concrete type that definitely accepts Integer like List<Object>
, List<Number>
or List<Integer>
.
Note that declaring that <T extends Integer>
will not let you add an Integer to the list either. Integer is final but in an imaginary made-up Java where it's not, we could declare a Generator<IntegerSubtype>
which would proceed to add an Integer to a List<IntegerSubtype>
. This might later result in an Integer
getting casted to an IntegerSubtype
so it's not allowed.
A simplified example of the last point is like this:
class ListHolder<T extends Object> {
List<T> list = new ArrayList<>();
ListHolder() {
list.add(new Object());
}
}
(And this serves to illustrate the rest as well since an unbounded type parameter would normally have Object as an upper limit.)
T
is bounded but it's more obvious that the list may very well not be able to hold Object. Actually since Object has no superclass, an Object can't be put in anything except a List<Object>
. By putting an Object in the list we might be (and probably are) later going to end up incorrectly downcasting it in to a subtype.
If we supply a concrete type to a list, from the outside this same add just looks like this:
List<String> list = new ArrayList<>();
list.add(new Object()); // Object would be casted to String
It's the same thing for Integer, this is just implausible:
List<IntegerSubtype> list = new ArrayList<>();
list.add(new Integer(3)); // Integer would be casted to IntegerSubtype
(I say just 'implausible' because I'm thinking it might be possible to spoof a subtype of a final class using sun.misc.Unsafe
...impossible in normal Java.)