因为编译器可以从变量声明中推断出类型。
例如:
List<String> list = Lists.newArrayList(),
编译器将理解集合的类型(即 E 的类型)将为 <String>
,因为您希望获得一个字符串列表。
使用Java7和钻石操作符,可以避免重写整个<>参数,这非常有用。
List<String> list = new ArrayList<>();
(假设它是一个List<List<String>>
,你应该重写为List<List<String>>
)
我为您找到了以下内容:
Java编译器利用目标类型来推断泛型方法调用的类型参数。表达式的目标类型是Java编译器根据表达式出现的位置所期望的数据类型。考虑如下声明的`Collections.emptyList()`方法:
static <T> List<T> emptyList();
考虑以下赋值语句:
List<String> listOne = Collections.emptyList()
这个语句期望一个 List 实例;这个数据类型是目标类型。因为 emptyList 方法返回 List 类型的值,编译器推断类型参数 T 必须是 String 值。这在 Java SE 7 和 8 中都有效。或者,你可以使用类型证明并指定 T 的值如下:
List<String> listOne = Collections.<String>emptyList()
然而,在这个上下文中并不需要这样做。虽然在其他情况下需要这样做。考虑以下方法:
void processStringList(List<String> stringList) {
}
假设您想使用空列表调用processStringList方法。在Java SE 7中,以下语句无法编译:
processStringList(Collections.emptyList())
Java SE 7编译器会生成类似以下的错误信息:
List<Object> cannot be converted to List<String>
编译器需要一个类型参数T的值,所以它从Object值开始。因此,调用Collections.emptyList返回一个List类型的值,该值与processStringList方法不兼容。因此,在Java SE 7中,必须按以下方式指定类型参数的值:
processStringList(Collections.<String>emptyList());
在Java SE 8中,这已经不再是必需的。目标类型的概念已经扩展到包括方法参数,例如方法processStringList的参数。在这种情况下,processStringList需要一个类型为List的参数。方法Collections.emptyList返回一个List值,因此使用List作为目标类型,编译器推断出类型参数T具有String值。因此,在Java SE 8中,以下语句可以编译:
processStringList(Collections.emptyList())
有关lambda表达式中目标类型的更多信息,请参见目标类型化。
阅读此文档。
Lists.newArrayListWithCapacity(5)
而不是new ArrayList<>(5)
),而且对于Lists.newArrayList("a", "b", "c")
也没有更好的替代方法。 - Tavian Barnes