此代码是否利用 Java 编译器泛型验证限制
Does this code exploit Java compiler generics verification limitations
在重构代码时,我偶然发现了奇怪的 Java 编译器 (Oracle 1.8.0_101) 行为。我的假设是,如果我用 T
替换所有出现的 List<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) {
}
此代码compiles。当我将 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) {
}
它 does not compile 再:
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
在重构代码时,我偶然发现了奇怪的 Java 编译器 (Oracle 1.8.0_101) 行为。我的假设是,如果我用 T
替换所有出现的 List<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) {
}
此代码compiles。当我将 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) {
}
它 does not compile 再:
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