13

I found in the util.TreeSet class that one of the constructor is calling another constructor with a new TreeMap with empty generic type.

  public TreeSet(Comparator<? super E> comparator) {
         this(new TreeMap<>(comparator));
  }

What does new TreeMap<> mean ? is that equivalent to new TreeMap<?> ?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
peter
  • 8,333
  • 17
  • 71
  • 94

2 Answers2

18

This is Java 7 syntax. The diamond (<>) is a short-hand to ask the Java compiler to fill generic arguments with whatever makes sense in the local context (in this case, it'll be ? super E).

Romain
  • 12,679
  • 3
  • 41
  • 54
  • The bytecode generated is backward-compatible, since Javac only fills in for you there. The source file needs to be compiled w/ JDK 7. – Romain Aug 10 '12 at 14:38
  • what do you mean ? you mean i can write the code in any version prior to 1.7 but the compiler has to be 1.7. Correct ? – peter Aug 10 '12 at 14:42
  • Also is <> strictly equivalent to > – peter Aug 10 '12 at 14:43
  • 2
    @user1389813 the code using the Diamond is equals to ` super E>` in Java 7, if you use Java 6 or less to compile it, you will get a compiler error. – Luiggi Mendoza Aug 10 '12 at 14:53
  • 1
    Technically, due to type erasure there is nothing to fill in as such. Instead it doesn't check the type. If you have a type where this has to be filled in e.g. anonymous sub classes you can't use `<>` – Peter Lawrey Aug 10 '12 at 14:54
  • 2
    "in this case, it'll be `? super E`" No, `new TreeMap super E>()` is not valid – newacct Aug 10 '12 at 18:35
  • 1
    @user1389813: well, on one level, you can say it can "fill in" in the brackets anything that satisfies the bounds (in this case, anything that is a subtype of `E` will do; the simplest is `E` itself). But as Peter Lawrey said, since there is no difference in the generated code for different type parameters, the compiler doesn't really care what to "fill in". – newacct Aug 11 '12 at 20:44
4

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.

  • 1
    Actually, the compiler doesn't need to infer anything -- what goes inside the brackets has no effect on the compiled bytecode. – newacct Oct 10 '13 at 01:25
  • @newacct True , the compiled bytecode is unaffected. But the compiler will "treat" TreeMap<> as if it was written TreeMap in the above case. In fact , the TreeSet(Comparator) constructor above invokes another TreeSet constructor that takes in a NavigableMap as an argument. – Asem Abusbeit Oct 11 '13 at 13:29