13

我在util.TreeSet类中发现一个构造函数正在调用另一个TreeMap具有空泛型类型的新构造函数。

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

是什么new TreeMap<>意思?这相当于new TreeMap<?>

4

2 回答 2

18

这是 Java 7 语法。菱形 ( <>) 是一种简写形式,要求 Java 编译器使用本地上下文中有意义的任何内容填充泛型参数(在本例中为? super E)。

于 2012-08-10T14:35:01.590 回答
4

不,<?><>不一样。

<?>是“无界通配符”,自 Java 5 以来一直存在。此通配符允许(即匹配)类型绑定允许的任何内容,没有额外限制。通配符是以您可以在通用实例上进行的操作为代价的。有关通配符的更多信息,请阅读相关的java 教程部分。要了解哪些通配符允许使用哪种类型界限,请查看此博客

"<>"Java 7 中添加了菱形运算符 ,其目的是通过让编译器在调用构造函数时从上下文推断这些类型,从而使开发人员在创建泛型类型实例时避免不必要的冗长。

编译器推断出最具体的可能类型,如果可用,请考虑以下因素:

1- 传递给构造函数的参数类型。

2- 您在新实例分配到的引用中指定的类型(“=”分配的左侧部分)。

3-类型的擦除。

在您的示例中,编译器将替换new TreeMap<>(comparator)new TreeMap<E,Object>(comparator).

要了解原因,请查看TreeMap<K,V>正在调用的构造函数:TreeMap(Comparator<? super K> comparator)

编译器需要推断K和的类型V。它期望 aComparator<? super K>并找到 aComparator<? super E>被传入,没有左手赋值,并且编译器不会有E被分配给的问题K(任何匹配 anE都将匹配 a K,因为它们具有相同的擦除),它得出结论K= E

因为V,同样没有左手赋值,没有传递给构造函数的参数,所以它留下了与擦除到V中指定的类型相同的TreeMap<K,V>擦除Object,因此得出V= Object

好了,编译器推断出K=EV= Object,语句变为TreeMap<E,Object>(comparator).

值得一提的是,虽然菱形运算符推断正在创建的实例的泛型类型,但它不会推断被调用的构造函数的泛型类型,以防万一它是泛型的,因为可以使用泛型类型变量定义构造函数就像您定义泛型方法(在其中添加未在类中定义的其他类型)一样,这些类型也受到编译器的推断,类似于它为泛型方法推断类型的方式,而不是通过菱形运算符。

于 2013-10-09T17:39:00.877 回答