我在util.TreeSet
类中发现一个构造函数正在调用另一个TreeMap
具有空泛型类型的新构造函数。
public TreeSet(Comparator<? super E> comparator) {
this(new TreeMap<>(comparator));
}
是什么new TreeMap<>
意思?这相当于new TreeMap<?>
?
这是 Java 7 语法。菱形 ( <>
) 是一种简写形式,要求 Java 编译器使用本地上下文中有意义的任何内容填充泛型参数(在本例中为? super E
)。
不,<?>
和 <>
不一样。
<?>
是“无界通配符”,自 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
=E
和V
= Object
,语句变为TreeMap<E,Object>(comparator)
.
值得一提的是,虽然菱形运算符推断正在创建的实例的泛型类型,但它不会推断被调用的构造函数的泛型类型,以防万一它是泛型的,因为可以使用泛型类型变量定义构造函数就像您定义泛型方法(在其中添加未在类中定义的其他类型)一样,这些类型也受到编译器的推断,类似于它为泛型方法推断类型的方式,而不是通过菱形运算符。