【发布时间】:2017-07-05 10:01:50
【问题描述】:
我对 Java 的类型推断有疑问。我使用的是 javac 1.8.0_121,下面的代码可以用 Eclipse ECJ 编译,但不能用 javac
import java.util.function.Function;
public class Playbook {
static class A {
}
static class B {
}
static class P<T> {
}
static class V<T> {
static <T, U> V<U> m(P<T> src, Function<? super T, ? extends U> f, Function<? super U, ? extends T> g) {
return null;
}
void b(final P<T> other) {
}
}
public void bindTimeString1(P<A> p1, P<B> p2) {
V.m(p2, s -> new A(), t -> new B()).b(p1);
}
}
用 javac 编译会导致以下错误:
[ERROR] Playbook.java:[31,47] incompatible types: main.java.Playbook.P<main.java.Playbook.A> cannot be converted to main.java.Playbook.P<java.lang.Object>
没有m的第二个参数g,代码编译没有问题:
导入 java.util.function.Function;
public class Playbook {
static class A {
}
static class B {
}
static class P<T> {
}
static class V<T> {
static <T, U> V<U> m(P<T> src, Function<? super T, ? extends U> f) {
return null;
}
void b(P<T> other) {
}
}
public void bindTimeString2(P<A> p1, P<B> p2) {
V.m(p2, s -> new A()).b(p1);
}
}
我不明白为什么这首先会失败。从代码中,编译器可以推断:
- f 返回扩展 U 的东西。
- g 接受 U 的基类。
- 从 g 的身体中无法推断出更多关于 U 的信息。
- 从 f 的主体,它知道它返回一个 A,所以 A <: u>
- Var.b 不再对 U 施加任何约束,因此 U 可以是满足 A <: u a object>
似乎当g存在时编译器选择了Object,但是m是一元时的A,虽然g没有添加任何关于U的东西。
如果这是 ECJ 或 javac 中的问题,我也感到困惑,因为 ECJ 接受代码而 javac 不接受。只有其中一个是正确的。
【问题讨论】:
标签: java type-inference