java - JDK 8 的类型推断如何与泛型一起工作?

标签 java generics java-8 type-inference

我的代码无法使用 JDK 7 进行编译,但可以使用 JDK 8 进行编译。

抽象实际代码:

interface A {
...
}

class B implements A {
...
}

public void AAA(List<A> list) {...}

AAA(Collections.singletonList(new B()));

Collections.singletonList 定义为

public static <T> List<T> singletonList(T o) {
    return new SingletonList<>(o);
}

据我所知,基于泛型,T 将被推断为 B,因此 Collections.singletonList(new B()) 将是无法分配给 List 的列表,因为 Java 泛型是不变的。

但是对于 JDK 8,T 被推断为 A 并且编译成功。

我想知道如何将 T 推断为 A,因为这里有两个类型 T 的变量:A 和 B。

有先后顺序吗?还是编译器找到共同的祖先类?

附上官方文档更胜一筹!

提前致谢!

ps1。 JDK 7版本为Oracle 1.7.0_79,JDK 8版本为Oracle 1.8.0_66。

PS2。以下是实际代码的链接:

https://github.com/apache/storm/blob/85a31e2fdec1ffef83e1ff438cd765a821fb06e4/examples/storm-opentsdb-examples/src/main/java/org/apache/storm/opentsdb/SampleOpenTsdbBoltTopology.java#L48

https://github.com/apache/storm/blob/85a31e2fdec1ffef83e1ff438cd765a821fb06e4/external/storm-opentsdb/src/main/java/org/apache/storm/opentsdb/bolt/OpenTsdbBolt.java#L77

https://github.com/apache/storm/blob/85a31e2fdec1ffef83e1ff438cd765a821fb06e4/external/storm-opentsdb/src/main/java/org/apache/storm/opentsdb/bolt/TupleOpenTsdbDatapointMapper.java#L37

最佳答案

嗯,有一个全新的章节,§18. Type Inference , 在语言规范中,但它并不容易阅读。即使是第一部分的摘要(准确地解决您的问题)也很难:

In comparison to the Java SE 7 Edition of The Java® Language Specification, important changes to inference include:

  • Adding support for lambda expressions and method references as method invocation arguments.
  • Generalizing to define inference in terms of poly expressions, which may not have well-defined types until after inference is complete. This has the notable effect of improving inference for nested generic method and diamond constructor invocations.
  • Describing how inference is used to handle wildcard-parameterized functional interface target types and most specific method analysis.
  • Clarifying the distinction between invocation applicability testing (which involves only the invocation arguments) and invocation type inference (which incorporates a target type).
  • Delaying resolution of all inference variables, even those with lower bounds, until invocation type inference, in order to get better results.
  • Improving inference behavior for interdependent (or self-dependent) variables.
  • Eliminating bugs and potential sources of confusion. This revision more carefully and precisely handles the distinction between specific conversion contexts and subtyping, and describes reduction by paralleling the corresponding non-inference relations. Where there are intentional departures from the non-inference relations, these are explicitly identified as such.
  • Laying a foundation for future evolution: enhancements to or new applications of inference will be easier to integrate into the specification.

第二个项目符号对您的代码示例影响最大。你有一个泛型方法的嵌套方法调用,没有指定显式类型参数,这使它成为一个所谓的聚合表达式,其实际类型可以从目标类型推断出来,这是AAA的参数类型在你的情况下。

所以这是一个相当简单的星座 AAA不是通用的,关于它的参数类型没有歧义。总是List<A> .这里没有搜索“公共(public)祖先类”,所有需要检查的是参数表达式的类型 ( B ) 是否与推断类型 ( A ) 兼容。

关于java - JDK 8 的类型推断如何与泛型一起工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41744852/

相关文章:

JavaFx ImageView 不会在绑定(bind)到 VBox 的 fitWidthProperty 上调整大小

java - CompletableFuture 阻塞主线程

java - MiniMaxSum 通过了第一个测试用例,但因值较大而失败 (hackerrank)

Java:如何推导嵌套泛型类型

c# - 继承泛型构造函数 C#

将 DataRow 转换为 T 类型时,C# Int64Converter 无法从 System.Int64 错误转换

java - 为什么 Stream<T> 没有实现 Iterable<T>?

java - selenium RC中的空指针异常使用java

java - 如何与 Trackers 通信并获取 Peers 列表?

java - 在处理过程中使用 ToF 距离传感器从 USB 端口传输数据