作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
对于下面的代码片段:
import java.util.List;
public class Main {
interface Interface1<T> {}
interface Interface2<T> extends Interface1<T> {}
static class Bound {}
interface BoundedI1<T extends Bound> extends Interface1<T> {}
interface BoundedI2<T extends Bound> extends Interface2<T> {}
public static void main(String[] args) {
test((List<BoundedI2<?>>) null);
//test2((List<BoundedI2<?>>) null);
}
public static void test(List<? extends Interface2<? extends Bound>> list) { test2(list); }
public static void test2(List<? extends Interface1<? extends Bound>> list) {}
}
编译器对第一个调用没问题,但如果我取消对第二个调用的注释,编译器就会报错。这是类型推理系统中的错误,还是有人可以解释为什么 JLS 中的推理规则在这里失败?
在 6u43 和 7u45 Oracle JDK 上测试。
更新:似乎 eclipsec 接受得很好。不幸的是,我无法真正改变我们的工具链 :P,但发现编译器中的差异很有趣。
错误消息,由 ideone(酷工具 btw)打印:
Main.java:12: error: method test2 in class Main cannot be applied to given types;
test2((List<BoundedI2<?>>) null);
^
required: List<? extends Interface1<? extends Bound>>
found: List<BoundedI2<?>>
reason: actual argument List<BoundedI2<?>> cannot be converted to List<? extends Interface1<? extends Bound>> by method invocation conversion
更新 2:编译正常,这表明编译器确实认为 BoundedI2<?>
可分配给 Interface1<? extends Bound>
,这似乎更直接地与 JLS 相矛盾:
public class Main {
interface Interface1<T> {}
interface Interface2<T> extends Interface1<T> {}
static class Bound {}
interface BoundedI1<T extends Bound> extends Interface1<T> {}
interface BoundedI2<T extends Bound> extends Interface2<T> {}
public static void main(String[] args) {
test((List<BoundedI2<?>>) null);
//test2((List<BoundedI2<?>>) null);
test3((BoundedI2<?>) null);
}
public static void test(List<? extends Interface2<? extends Bound>> list) { test2(list); }
public static void test2(List<? extends Interface1<? extends Bound>> list) {}
public static void test3(Interface1<? extends Bound> instance) {}
}
最佳答案
看起来命令行编译器同时处理有一些困难
至少没有正确实例化 BoundedI2。确实奇怪的是,在同一个 JDK 上配置的 Eclipse 编译得很好......请注意,Eclipse 使用它的内部编译器来处理键入时的增量重新计算,因此它根本不调用 JDK 的编译器(请参阅 org/eclipse/jdt/internal/编译包)。
此修改通过强制 BoundedI2 为具体类型而不是类型推断,使其在 Eclipse 和命令行中都能正常编译:
import java.util.List;
public class PerfTest {
interface Interface1<T> {}
interface Interface2<T> extends Interface1<T> {}
static class Bound {}
interface BoundedI1<T extends Bound> extends Interface1<T> {}
interface BoundedI2<T extends Bound> extends Interface2<T> {}
static class Actual extends Bound {}
public static void main(String[] args) {
test((List<BoundedI2<Actual>>) null);
test2((List<BoundedI2<Actual>>) null);
}
public static void test(List<? extends Interface2<? extends Bound>> list) { test2(list); }
public static void test2(List<? extends Interface1<? extends Bound>> list) {}
}
关于Java 有界泛型 : Type inference bug?(方法调用,JLS 15.12.2.7),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24817306/
我是一名优秀的程序员,十分优秀!