我在util.TreeSet
类中发现其中一个构造函数正在使用具有空泛型类型的新TreeMap
调用另一个构造函数。
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
new TreeMap<>
是什么意思?这相当于new TreeMap<?>
?
答案 0 :(得分:17)
这是Java 7语法。菱形(<>
)是一个简单的方法,要求Java编译器用本地上下文中有意义的东西填充泛型参数(在这种情况下,它将是? super E
)。
答案 1 :(得分:3)
不,<?>
和<>
不一样。
<?>
是“无界的通配符”,自Java 5以来一直存在。此通配符允许(即匹配)类型绑定允许的任何内容,没有额外的限制。通配符是以您可以在通用实例上进行的操作为代价的。有关通配符的更多信息,请阅读java tutorial section on that.要了解允许哪些通配符与哪种类型边界,请查看this blog。
"<>"
。目的是通过让编译器在调用构造函数时从上下文中推断出这些类型,从而避免开发人员在创建泛型类型的实例时不必要地冗长。
编译器推断出可能的最具体类型,如果可用,则考虑以下因素:
1-传递给构造函数的参数类型。
2-您在分配新实例的引用中指定的类型(左侧 '='任务的一部分)。
3-类型的擦除。
在您的示例中,编译器将new TreeMap<>(comparator)
替换为new TreeMap<E,Object>(comparator)
。
要了解原因,请查看正在调用的TreeMap<K,V>
的构造函数:TreeMap(Comparator<? super K> comparator)
。
编译器需要推断K
和V
的类型。它需要Comparator<? super K>
并找到传入的Comparator<? super E>
,没有左手分配,并且编译器不会将E
分配给K
的问题(任何问题)匹配E
将与K
匹配,因为它们具有相同的删除率),结论是K
= E
。
对于V
,再次没有左手赋值,没有传递给构造函数的参数,因此留下V
中指定的类型TreeMap<K,V>
的删除擦除到Object
,因此V
= Object
得出结论。
有了它,编译器推断K
= E
和V
= Object
,语句变为TreeMap<E,Object>(comparator)
。
值得一提的是,虽然菱形运算符推断出正在创建的 实例 的泛型类型,但它并不推断<的通用类型< strong> 构造函数 在它是通用的情况下被调用,因为构造函数可以使用泛型类型变量定义,就像定义泛型方法一样(在这里添加未在类中定义的其他类型),这些类型也会受到编译器的推断,类似于推断泛型方法类型的方式,而不是通过菱形运算符。