No , <?>
and <>
are not the same.
<?>
is the "unbounded wildcard" and has been around since Java 5 . This wildcard allows (i.e. matches) anything that the type bound allows ,with no extra restrictions. Wildcards come at the cost of operations you can make on the generic instance. For more information on wildcards , read the java tutorial section on that. To read about which wildcards are allowed with which type bounds , check out this blog.
"<>"
, the diamond operator , was added in Java 7. the goal was to spare developers from being needlessly verbose when creating instances of generic types , by having the compiler infer those types from the context when calling the constructor.
The compiler infers for the most specific type(s) possible , factoring in the following if available :
1- The types of the arguments passed to the constructor.
2- The types you specify in the reference the new instance is assigned to (the left-hand
part of the '=' assignment).
3- The erasure for the types.
In your example , the compiler will replace new TreeMap<>(comparator)
with new TreeMap<E,Object>(comparator)
.
To understand why , take a look at the constructor for TreeMap<K,V>
that is being called : TreeMap(Comparator<? super K> comparator)
.
the compiler needs to infer types for K
and V
. It expects a Comparator<? super K>
and finds a Comparator<? super E>
being passed in , no left hand assignment , and the compiler would not have an issue with E
being assigned to K
(Anything that matches an E
would match a K
since they have same erasure ), it concludes that K
=E
.
For V
, again no left hand assignment , no parameters for that passed in to the constructor , so it is left with the erasure for the type V
as specified in TreeMap<K,V>
with erases to Object
, so concludes that V
=Object
.
There you have it , the compiler infers K
=E
, and V
=Object
, and the statement becomes TreeMap<E,Object>(comparator)
.
Worth mentioning that while the diamond operator infers the generic type(s) of the instance being created , it does NOT infer the generic type(s) of the constructor being called in case it was generic , as constructors can be defined with generic type variables just like you define generic methods (where you add additional types not defined in the class), and those types are also subject to inference by the compiler similar to the way it infers types for a generic method , not through the diamond operator.