这是我可以提出的最简单的测试来证明不一致性:
interface Foo<S extends Foo<S,T>,T> { // should this compile? public <X extends Foo<S,Y>,Y> Y method1(); // what about this? public <X extends Foo<? extends S,Y> Y method2();}
Oracle JDK在method1上给出了错误,但没有给出method2,而Eclipse对这两种方法都没有问题.我甚至不确定任何一种方法都应该编译……
如果这两个方法都不应该编译开始,那么以下几点没有实际意义,但我觉得如果我们添加以下代码,两个编译器都会出错:
interface bar extends Foo<bar,Integer> {}class BUG { voID BUG() { bar bar = null; Double bubble; // these fail as expected... bar.<Foo<bar,Double>,Double> method1(); bar.<Foo<? extends bar,Double> method2(); // ...but these don't even though the inferred parametrisations should be // the same as above Double bobble = bar.method1(); Double babble = bar.method2(); }}
当我们为method1和method2提供显式参数化时,我找不到任何会导致返回Double的有效调用(即,当使用Double参数化时,我找不到X的有效参数化).这是我期望的行为,就我所见,这里的Y应该只能用Integer参数化.
但是,当我们让编译器推断参数化时,Oracle JDK和Eclipse JDT都允许使用Y推断的调用为Double.如果将鼠标悬停在Eclipse中的调用上,它甚至会显示参数化与我们手动失败的参数化完全相同,那么为什么不同的行为呢?
(此时分配给新变量bobble和babble的原因是悬停文本显示不同的参数 – 由于某种原因将Double替换为Object – 如果我们再次分配给bubble.它仍然编译两个调用并分配给双打,所以我不知道为什么会这样.)
所以,这可能是我的另一个相当含糊的问题,但是这里的任何人都可以为我阐明这一点吗?
编辑:
Eclipse的错误报告:https://bugs.eclipse.org/bugs/show_bug.cgi?id=398011
解决方法 似乎编译器做了某种简化. Foo.method1和Foo.method2用两个参数X和Y声明,其中一个参数可以在推断期间确定,但是根本不使用X.因此,当您调用Double bobble = bar.method1()时,X应该计算为extends Foo< bar,但编译器决定删除此参数,因为它未被使用.
当您明确指定方法参数时,编译器必须检查它们的正确性并按预期失败.
如果您更改这些方法中的任何一个以接受类型X的参数,那么您将不会得到这种模糊的情况,因为您将为编译器提供一些信息,用于确定实际的X.
当Eclipse编译器根本没有显示任何错误时,Eclipse有几个这样的错误,但是javac开始抱怨不正确的方法调用.避免此类错误的最佳方法是使用显式参数,在这种情况下,大多数编译器的行为几乎相同.因此,如果您对显式参数有问题,最好重新设计您的类.
总结以上是内存溢出为你收集整理的Oracle JDK和Eclipse JDT编译器不一致!哪个不正确地编译?不寻常的泛型和差异全部内容,希望文章能够帮你解决Oracle JDK和Eclipse JDT编译器不一致!哪个不正确地编译?不寻常的泛型和差异所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)