[英]Need help in understanding Java tutorial on Generics
我正在从这里阅读Java教程。 我在理解一条简单的线时遇到了麻烦。
教程说Collections.emptyList
声明是:
static <T> List<T> emptyList();
因此,如果我们编写List<String> listOne = Collections.emptyList();
,它的工作方式是Java编译器能够推断出type参数,因为返回的值应为List<String>
类型。
现在考虑一个方法: void processStringList(List<String> stringList)
。 现在它说:
processStringList(Collections.emptyList()); Java SE 7编译器生成类似于以下内容的错误消息:
List <'Object>不能转换为List <'String>
编译器需要类型参数T的值,因此它以值Object开头。 因此,对Collections.emptyList的调用返回类型为
List<Object>
的值,该值与方法processStringList不兼容。
现在,它们的意思是: 所以它以值Object开头 ? 我的意思是开始做什么?
基本上,这与编译器的功能有关。 换句话说:在某种程度上,可能类型推断的“数量”是一个实现细节。
在Java 7中,有时必须使用类型helper / hints / witnesses,在其中使用Collections.<String>emptyList()
来告知编译器该缺失部分。
以后的编译器实现改善了您几乎总是可以使用Collections.emptyList()
。
关于The compiler requires a value for the type argument T so it starts with the value Object.
……实际上很简单:java编译器必须实现一种算法,最后才能推断出特定类型。 提供一些伪代码,可能类似于:
Class<?> inferType(SomeSyntaxTree construct) {
我只是在这里使用Class
来表示算法将返回类似于已知类型的东西。 现在,该方法可以这样实现:
Class<?> inferedType = Object.class
while (whatever) {
refine inferedType
}
return inferedType
换句话说:当您“搜索”某些值时,这是一种非常常见的方法:使用“最通用”值进行初始化(在Java类型系统中,它将是Object.class),然后查看该通用值可以通过应用任何算法来优化值。
在我们的例子中,优化可能最终会得出“可以使用的最特定类型是String
”的信息,但是如果无法进一步优化,则最终会出现“初始默认值”,即Object
。
该声明
processStringList(Collections.emptyList());
在Java 8中工作正常(我也假设在8以上)。 在这种情况下,编译器足够聪明,可以通过检查方法的预期参数类型来推断类型。
在旧版本中,当编译器看不到显式的返回类型时(如List<String> listOne = Collections.emptyList();
),默认情况下它将<T>
推断为java.lang.Object
。 但是请注意, List<Object>
和List<String>
不兼容。
您可以将方法声明为void processString(List<? super String> list)
以避免发生错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.