用于Java中奇怪的显式类型参数声明语法 [英] Uses for the strange-looking explicit type argument declaration syntax in Java

查看:285
本文介绍了用于Java中奇怪的显式类型参数声明语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近遇到了一些奇怪的语法,用于在调用Java方法时显式声明泛型类型。例如:

  Collections。< String> emptyList(); 

返回一个空的 List< String> 。然而,这看起来很愚蠢,因为< T> emptyList()就是未经检查的类型cast (List< T>)EMPTY_LIST ,所有结果都具有相同的类型擦除)另外,这种显式类型声明通常是不需要的,因为编译器通常可以推断出类型:

  List< ;字符串> empty = Collections.emptyList(); 

在做了更多的挖掘之后,我发现了另外两次你想要使用这种语法的地方,他们都是由于使用Guava库和显然试图在一行上放置太多声明


  1. 装饰一个集合,例如用一个同步包装器,并且编译器不能推断出这些类型。如果您取出类型声明,以下内容不起作用:不能从Set< Object>设置< String>

     设置< String> set = Collections.synchronizedSet(Sets。< String> newHashSet()); 


  2. 当编译器试图编写太特殊的类型参数时,例如,没有类型声明,下面的语句也会抱怨:不能从Map< String,String> Map< String,Object>

      Map< String,Object> toJson = ImmutableMap。< String,Object> of(foo,bar); 


我觉得在第一种情况下推断的类型参数过于笼统,第二种情况下它们太具体,但我想这只是Java中的泛型系统的一个工件。然而,除了这些 Guava团队发明的奇怪用例。此外,对于我来说, there 是编译器在上述两个示例中推断类型参数的一种方式,而开发人员只是选择不这样做。在Java编程中使用这个构造是否有必要或有用的例子,还是仅仅为了让编译器更简单/ JDK开发人员的生活更简单而举例说明? 方案

关闭编译器不是必要的还是有用的?我发现它对于我的代码编译来说都是很有用的。



有时无法推断正确的类型,因为您已经有了找到。在这种情况下,有必要明确指定类型参数。一些编译器的例子不够聪明:



如果你真的想挖掘到类型推断的复杂性,它以Java语言规范开始和结束。您需要关注 JLS§ 15.12.2.7。基于实际参数推断类型参数§ 15.12.2.8。推断未解决的类型参数


I recently came upon the strange syntax for explicitly declaring generic types when calling Java methods. For example:

Collections.<String>emptyList();

returns an empty List<String>. However, this seems silly as the implementation of <T> emptyList() is just the unchecked type cast (List<T>) EMPTY_LIST, such that all results have the same type erasure (and are the same object.) Moreover, this sort of explicit type declaration is usually not needed because the compiler can often infer the types:

List<String> empty = Collections.emptyList();

After doing some more digging I found two other times where you'd want to use this syntax, and they're all due to using the Guava library and apparently trying to put too many statements on one line.

  1. 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());
    

  2. 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");
    

I find it ironic that in the first case the inferred type parameters are too general and in the second case they are too specific, but I suppose that is just an artifact of the generics system in Java.

However, this language construct itself seems to be avoidable except in these strange use cases invented by the Guava team. Moreover, it seems plain to me that there is a way for the compiler to infer type arguments in both the above examples, and the developers just chose not to do so. Are there examples of it ever being necessary or useful to use this construct in Java programming or does it exist solely to make the compiler simpler / JDK developer's life easier?

解决方案

How is "shutting up the compiler" not "necessary or useful?" I find it both necessary and useful for my code to compile.

There are times when the correct type cannot be inferred, as you have already found. In such cases, it is necessary to explicitly specify the type parameters. Some examples of the compiler just not being smart enough:

And if you really want to dig into the complexities of type inference, it starts and ends with the Java Language Specification. You'll want to focus on JLS §15.12.2.7. Inferring Type Arguments Based on Actual Arguments and §15.12.2.8. Inferring Unresolved Type Arguments.

这篇关于用于Java中奇怪的显式类型参数声明语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆