简体   繁体   English

需要帮助以了解有关泛型的Java教程

[英]Need help in understanding Java tutorial on Generics

I was reading a Java tutorial from here . 我正在从这里阅读Java教程。 I am having trouble understanding a simple line. 我在理解一条简单的线时遇到了麻烦。

Tutorial says declaration of Collections.emptyList is: 教程说Collections.emptyList声明是:

static <T> List<T> emptyList();

So if we write List<String> listOne = Collections.emptyList(); 因此,如果我们编写List<String> listOne = Collections.emptyList(); , it works as the Java compiler is able to infer the type parameter, as the returned value should be of type List<String> . ,它的工作方式是Java编译器能够推断出type参数,因为返回的值应为List<String>类型。

Now consider a method: void processStringList(List<String> stringList) . 现在考虑一个方法: void processStringList(List<String> stringList) Now it states: 现在它说:

processStringList(Collections.emptyList()); processStringList(Collections.emptyList()); The Java SE 7 compiler generates an error message similar to the following: Java SE 7编译器生成类似于以下内容的错误消息:

List<'Object> cannot be converted to List<'String> List <'Object>不能转换为List <'String>

The compiler requires a value for the type argument T so it starts with the value Object. 编译器需要类型参数T的值,因此它以值Object开头。 Consequently, the invocation of Collections.emptyList returns a value of type List<Object> , which is incompatible with the method processStringList 因此,对Collections.emptyList的调用返回类型为List<Object>的值,该值与方法processStringList不兼容。

Now what do they mean by: so it starts with the value Object ? 现在,它们的意思是: 所以它以值Object开头 I mean start doing what? 我的意思是开始做什么?

Basically this is about the capabilities of the compiler. 基本上,这与编译器的功能有关。 In other words: to a certain degree, the "amount" of possible type inference is an implementation detail. 换句话说:在某种程度上,可能类型推断的“数量”是一个实现细节。

With Java 7, you sometimes have to use type helpers/hints/witnesses, where you would go Collections.<String>emptyList() to tell the compiler about that missing part. 在Java 7中,有时必须使用类型helper / hints / witnesses,在其中使用Collections.<String>emptyList()来告知编译器该缺失部分。

Later implementations of the compiler improved the situation that you can almost always go with Collections.emptyList() . 以后的编译器实现改善了您几乎总是可以使用Collections.emptyList()

Regarding The compiler requires a value for the type argument T so it starts with the value Object. 关于The compiler requires a value for the type argument T so it starts with the value Object. ... that is actually quite simple: the java compiler has to implement an algorithm, that finally, infers a specific type. ……实际上很简单:java编译器必须实现一种算法,最后才能推断出特定类型。 Giving some pseudo-code, that might look like: 提供一些伪代码,可能类似于:

Class<?> inferType(SomeSyntaxTree construct) {

I am just using Class here to indicate that the algorithm will return something that resembles a known type. 我只是在这里使用Class来表示算法将返回类似于已知类型的东西。 Now, that method could be implemented like this: 现在,该方法可以这样实现:

 Class<?> inferedType = Object.class
 while (whatever) {
   refine inferedType
 }
 return inferedType

In other words: that is a very common approach when you "search" for some value: you initialize with the "most generic" value (in the Java type system, that would be Object.class), and then you see if that generic value can be refined by applying whatever algorithm. 换句话说:当您“搜索”某些值时,这是一种非常常见的方法:使用“最通用”值进行初始化(在Java类型系统中,它将是Object.class),然后查看该通用值可以通过应用任何算法来优化值。

In our case, the refinement might end up in figuring "the most specific type that can be used is String ", but if no further refinement is possible, then you end up with your "initial default", being Object . 在我们的例子中,优化可能最终会得出“可以使用的最特定类型是String ”的信息,但是如果无法进一步优化,则最终会出现“初始默认值”,即Object

The statement 该声明

processStringList(Collections.emptyList());

works fine in Java 8 (I'm assuming above 8 as well). 在Java 8中工作正常(我也假设在8以上)。 The compiler in this case is smart enough to infer the types by checking what is the expected argument type for the method. 在这种情况下,编译器足够聪明,可以通过检查方法的预期参数类型来推断类型。

In older versions, when compiler sees no explicit return type (as in List<String> listOne = Collections.emptyList(); ), it by default infers <T> to java.lang.Object . 在旧版本中,当编译器看不到显式的返回类型时(如List<String> listOne = Collections.emptyList(); ),默认情况下它将<T>推断为java.lang.Object But note that List<Object> and List<String> are not compatible. 但是请注意, List<Object>List<String>不兼容。

You can declare the method like void processString(List<? super String> list) to avoid the error. 您可以将方法声明为void processString(List<? super String> list)以避免发生错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM