我遇到了 Java 编译器的一个完全奇怪的行为。
当 cyclic generic type 时,我无法将父类(super class)型转换为子类型
涉及关系。
JUnit 测试用例 重现问题:
public class _SupertypeGenericTest {
interface ISpace<S extends ISpace<S, A>, A extends IAtom<S, A>> {
}
interface IAtom<S extends ISpace<S, A>, A extends IAtom<S, A>> {
}
static class Space
implements ISpace<Space, Atom> {
}
static class Atom
implements IAtom<Space, Atom> {
}
public void test() {
ISpace<?, ?> spaceSupertype = new Space();
IAtom<?, ?> atomSupertype = new Atom();
Space space = (Space) spaceSupertype; // cast error
Atom atom = (Atom) atomSupertype; // cast error
}
}
编译器错误输出:
_SupertypeGenericTest.java:33: inconvertible types
found : pinetag.data._SupertypeGenericTest.ISpace<capture#341 of ?,capture#820 of ?>
required: pinetag.data._SupertypeGenericTest.Space
Space space = (Space) spaceSupertype;
^
_SupertypeGenericTest.java:34: inconvertible types
found : pinetag.data._SupertypeGenericTest.IAtom<capture#94 of ?,capture#48 of ?>
required: pinetag.data._SupertypeGenericTest.Atom
Atom atom = (Atom) atomSupertype;
^
2 errors
注意:我使用的是 Netbeans 最新的主干、捆绑的 Ant、最新的 Java 6 版本。
我尝试从命令行使用 Ant(Netbeans 生成一个 build.xml 文件)
但它会导致相同的错误。
怎么了?
有没有优雅的方法解决这个问题?
奇怪的是:Netbeans 不标记错误(甚至不标记警告) 在给定的代码中。
编辑:
不,现在我什么都不懂了!
Eclipse 3.4.1 既不标记警告也不标记错误,并且编译
代码没有问题!!!
怎么会这样?我想,从命令行使用 Ant 以及
Netbeans 提供的 build.xml 将是中性的。
我错过了什么吗?
编辑 2:
使用JDK7库和JDK7代码格式,netbeans编译无
错误/警告!
(我使用的是 1.7.0-ea-b55)
编辑 3:
更改标题以表明我们正在处理 javac 错误。
最佳答案
我并不声称可以轻松理解那些复杂的泛型类型,但是如果您发现一些代码可以在 javac
中编译而不能在 ecj
中编译(eclipse 编译器), 然后用 Sun 提交错误报告和 Eclipse并清楚地描述情况(如果您还提到您提交了两个错误报告并提及它们各自的 URL 最好,尽管对于 Sun 来说可能需要一段时间才能公开访问该错误)。
我过去曾经这样做过,并且得到了很好的回应
- 其中一个团队找出了正确的方法(给出编译错误、警告或什么都不给出)
- 错误的编译器已修复
由于两个编译器实现了相同的规范,如果只有其中一个编译代码,那么其中一个编译器根据定义是错误的。
备案:
我尝试用 javac
(javac 1.6.0_13) 和 ecj
(Eclipse Java Compiler 0.894_R34x, 3.4.2 release) 和 编译示例代码javac
大声提示并未能生成任何 .class
文件,而 ecj
仅提示一些未使用的变量(警告)并生成了所有预期的 。类
文件。
关于Java:循环泛型类型关系不允许从父类(super class)型转换(javac 错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/804247/