我最近发现了在调用Java方法时显式声明泛型类型的奇怪语法。例如:
Collections.<String>emptyList();
返回一个空的 List<String>
。然而,这似乎有些愚蠢,因为<T> emptyList()
的实现只是未经检查的类型转换 (List<T>) EMPTY_LIST
,因此所有结果都具有相同的类型擦除(并且是同一个对象)。此外,通常不需要这种明确的类型声明,因为编译器通常可以推断出类型:
List<String> empty = Collections.emptyList();
在进一步调查后,我发现还有两种情况需要使用这种语法,都是由于使用Guava库并且明显尝试将太多语句放在一行上导致的。
Decorating a collection, for example with a synchronized wrapper, and the compiler being not able to infer the types. The following doesn't work if you take out the type declaration:
cannot convert from Set<Object> to Set<String>
:Set<String> set = Collections.synchronizedSet(Sets.<String>newHashSet());
Getting less specific type parameters when they compiler tries to make ones that are too specific. For example, without the type declaration the following statement complains as well:
cannot convert from Map<String, String> to Map<String, Object>
:Map<String, Object> toJson = ImmutableMap.<String, Object>of("foo", "bar");
我觉得有些讽刺的是,在第一个情况中,推断出的类型参数过于泛化,而在第二种情况中则过于具体,但我想这只是Java中泛型系统的一种产物。
然而,这种语言结构本身似乎是可以避免的,除了在Guava团队发明的奇怪用例之外。此外,对我来说,编译器在上述两个示例中都可以推断出类型参数,开发人员只是选择不这样做。在Java编程中是否存在必须或有用使用这种结构的示例,还是它仅存在于使编译器更简单/ JDK开发人员更轻松的目的?
Collections.synchronizedSet(new HashSet<String>())
。 - Louis Wasserman