You are confusing the parameterized type with the concrete type.
Given List<T>
, T
is the parameterized type.
List<String>
isn't type related to List<Object>
in any way, not anymore than List<String>
is related to List<Number>
. The type
is List<String>
, the entire signature is the type
. But like with everything, there are exceptions; these are called Wildcard Parameterized Types
.
List<?>
is what is called an Unbounded Wildcard Parameterized Type, it works pretty much just like a raw type, they are semantically the same, but causes more compiler warnings about unsafe casting.
List<? extends Object>
is a bounded Wildcard Parameterized Type, and would be a type that would allow you to put anything that extends Object
but since every class in Java extends Object
it isn't semantically any different than the first two options.
Now they would all function the same, but they would fail instanceof
tests, they are not the same types.
In other words:
public void myfunction(final List<Object> list) {}
would only accept the type
of List<Object>
, List
isn't related by type
to List<Object>
or List<?>
, even though they all semantically function the same.
The type
is either List
or List<Object>
or List<String>
, the inheritance chain in the <>
is not considered when the type of the List<T>
is concerned, until you get into Wild Card Parameterized Types
Here are examples:
Collection<?> coll = new ArrayList<String>();
List<? extends Number> list = new ArrayList<Long>();
You can't instantiate a new Collection<?>
only assign a concrete implementation to it.
List<Object>
is the entire type.
Generics in Java aren't anything like the implementation in C++, other than the confusing name.