升级Java与Eclipse后重写泛型外部类内部类出现编译错误
首先,这个问题的核心是Eclipse的Java编译器(ECJ)在Java 8版本中对泛型内部类的类型检查变得更加严格,完全遵循Java语言规范的要求,而旧版本的ECJ(对应Eclipse 3.7.2 + Java 1.7)对这类场景做了宽松处理,允许模糊的类型引用。
错误原因分析
1. 方法重写的名字冲突(Name clash)
在TestB中,你直接写InnerGeneric作为方法参数类型时,Java 8的ECJ会将其解析为TestGeneric.InnerGeneric(原始类型,未绑定泛型参数),而TestA中的someMethod参数类型是TestGeneric<TestSomeObject>.InnerGeneric(已经绑定了具体的泛型参数)。虽然两者的类型擦除结果一致,但实际类型并不兼容,因此编译器认为这不是合法的重写,而是一个新的方法,从而触发“名字冲突”错误。
2. 构造器未定义错误
同样的道理,InnerB的构造器中传递的InnerGeneric是原始类型,而InnerA的构造器需要的是绑定了TestSomeObject的TestGeneric<TestSomeObject>.InnerGeneric类型,两者类型不匹配,所以编译器提示构造器未定义。
解决方案
解决这个问题的关键是明确指定InnerGeneric的具体类型,绑定到父类TestA中已经确定的泛型版本。你只需要在TestB中所有引用InnerGeneric的地方,加上TestA.前缀(或者使用super.前缀),让编译器明确知道你引用的是TestA中已经绑定了泛型参数的内部类。
修改后的TestB.java代码如下:
package a; import a.TestA; public class TestB extends TestA { public TestB(String a, String b){ super(a,b); } // 明确使用TestA中的InnerGeneric类型 public InnerA someMethod(String some, TestA.InnerGeneric inner) { return new InnerB(some, inner); } protected class InnerB extends InnerA { // 构造器参数同样指定为TestA.InnerGeneric public InnerB(String a, TestA.InnerGeneric b) { super(a, b); } } }
这样修改后,编译器就能正确识别TestB的someMethod是对TestA方法的合法重写,同时InnerB构造器传递的参数类型也和InnerA构造器的要求完全匹配,两个编译错误都会消失。
内容的提问来源于stack exchange,提问作者emi-le

