是钻石运营商&lt;&gt;相当于<! - ? - >

时间:2012-08-10 14:33:00

标签: java generics

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

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

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

2 个答案:

答案 0 :(得分:17)

这是Java 7语法。菱形(<>)是一个简单的方法,要求Java编译器用本地上下文中有意义的东西填充泛型参数(在这种情况下,它将是? super E)。

答案 1 :(得分:3)

不,<?><>不一样。

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

在Java 7中添加了钻石算子

"<>"。目的是通过让编译器在调用构造函数时从上下文中推断出这些类型,从而避免开发人员在创建泛型类型的实例时不必要地冗长。

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

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

2-您在分配新实例的引用中指定的类型(左侧 '='任务的一部分)。

3-类型的擦除。

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

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

编译器需要推断KV的类型。它需要Comparator<? super K>并找到传入的Comparator<? super E>,没有左手分配,并且编译器不会将E分配给K的问题(任何问题)匹配E将与K匹配,因为它们具有相同的删除率),结论是K = E

对于V,再次没有左手赋值,没有传递给构造函数的参数,因此留下V中指定的类型TreeMap<K,V>的删除擦除到Object,因此V = Object得出结论。

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

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