重构代码时,我偶然发现了奇怪的Java编译器(Oracle 1.8.0_101)行为。我的假设是,如果我替换所有出现List<T>
的T
(不使用任何方法从List
)的代码应该编译,如果它改变之前编译。
现在看一下这段代码:
interface Mapper<T, U extends MapperProvider<U>> extends Function<T, List<U>> {}
interface MapperProvider<V> {
Mapper<V, ?> provide();
}
private <V extends MapperProvider<V>> void use(V c) {
use2(c.provide().apply(c));
}
private <W extends MapperProvider<W>> void use2(List<W> c) {
}
此代码进行编译。当我更换List<U>
由U
并且List<W>
通过W
:
interface Mapper<T, U extends MapperProvider<U>> extends Function<T, U> {}
interface MapperProvider<V> {
Mapper<V, ?> provide();
}
private <V extends MapperProvider<V>> void use(V c) {
use2(c.provide().apply(c));
}
private <W extends MapperProvider<W>> void use2(W c) {
}
它不再编译:
Error:(201, 17) java: method use2 in class Test cannot be applied to given types;
required: W
found: capture#1 of ?
reason: inference variable W has incompatible bounds
equality constraints: capture#1 of ?
lower bounds: MapperProvider<capture#1 of ?>
从我的角度来看这是正确的。use2
应该声明要接收MapperProvider<?>
。
为什么Java编译器将第一个版本视为合法版本?
看起来Oracle认为这是一个错误。我打开了一个错误报告,Oracle确认:JDK-8172222
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句