我的代码无法使用JDK 7编译,但成功使用JDK 8进行编译.
要抽象实际代码:
interface A { ... } class B implements A { ... } public void AAA(List list) {...} AAA(Collections.singletonList(new B()));
Collections.singletonList定义为
public staticList singletonList(T o) { return new SingletonList<>(o); }
因此,据我所知,基于泛型,T将被推断为B,因此Collections.singletonList(new B())将是List,由于Java泛型是不变的,因此无法将其分配给List.
但是使用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.在语言规范中键入推理,但这并不容易阅读.即使是第一部分的摘要,也很难解决你的问题,但很难:
与Java®语言规范的Java SE 7版相比,推理的重要变化包括:
添加对lambda表达式和方法引用的支持作为方法调用参数.
推广用多边形表达式定义推理,在推理完成之前,可能没有明确定义的类型.这具有改进嵌套泛型方法和菱形构造函数调用的推断的显着效果.
描述如何使用推理来处理通配符参数化的功能接口目标类型和最具体的方法分析.
澄清调用适用性测试(仅涉及调用参数)和调用类型推断(包含目标类型)之间的区别.
延迟所有推理变量的解析,甚至是那些具有下限的推理变量,直到调用类型推断,以便获得更好的结果.
改善相互依赖(或自相关)变量的推理行为.
消除错误和潜在的混淆源.该修订更仔细和精确地处理特定转换上下文和子类型之间的区别,并通过并行相应的非推理关系来描述减少.如果故意偏离非推理关系,则明确指出这些关系.
为未来发展奠定基础:推理的增强或新应用将更容易集成到规范中.
第二个项目符号对您的代码示例影响最大.您有一个泛型方法的嵌套方法调用,而没有指定显式类型参数,这使得它成为一个所谓的多表达式,其实际类型可能是从目标类型推断出来的,这是AAA
您案例中的参数类型.
所以这是一个相当容易的星座,因为AAA
它不是通用的,并且没有关于它的参数类型的歧义.它始终是List
.这里没有搜索"共同的祖先类",所有必须检查的是参数表达式的type(B
)是否与推断的类型(A
)兼容.