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