泛型接口方法共享抽象实现报错:未覆盖超类方法原因排查
咱们来一步步拆解这个问题,核心原因是泛型接口实现时的参数遗漏和Java的泛型类型擦除机制共同导致的方法签名不匹配。
1. 问题的直接诱因:抽象类实现接口时未指定泛型参数
看你的抽象类声明:
public abstract class SharedValidator<T extends Document> implements Validator {
这里你写的是implements Validator——没有指定接口的泛型参数,这相当于使用了**原始类型(raw type)**的Validator接口。
在Java中,当你使用泛型类/接口的原始类型时,编译器会擦除所有泛型信息,把接口的方法签名还原到泛型定义的上限类型。你的Validator接口泛型是<T extends Document>,所以擦除后接口的方法签名变成:
boolean isValid(Document document) throws DocumentValidationException
而你的抽象类里的方法是:
@Override public boolean isValid(final T document) throws DocumentValidationException { ... }
这里的T是抽象类自己声明的泛型参数(T extends Document),虽然T是Document的子类,但编译器会认为这是一个重载方法,而不是对接口方法的覆盖——因为原始类型接口的方法参数是Document,而你的方法参数是泛型T,签名不匹配,所以@Override注解就会报错,提示没有覆盖超类方法。
2. 修复方案:绑定接口与抽象类的泛型参数
只需要修改抽象类的实现声明,把接口的泛型参数和抽象类的泛型参数绑定起来,也就是实现Validator<T>而不是原始类型的Validator:
public abstract class SharedValidator<T extends Document> implements Validator<T> { @Override public boolean isValid(final T document) throws DocumentValidationException { if (null == document) { return false; } else { return true; } } }
这样一来,接口的泛型T和抽象类的泛型T完全对应,方法签名isValid(T)就和接口的方法签名完全匹配,@Override注解会正常生效,编译器也不会再报错。
3. 额外验证:子类的正确性
你的两个子类ValidatorA和ValidatorB的写法是正确的:
public class ValidatorA extends SharedValidator<DocumentA> { } public class ValidatorB extends SharedValidator<DocumentB> { }
它们会自动继承抽象类的isValid方法,并且参数类型会被替换为DocumentA和DocumentB,完全符合你“抽象类提供通用实现,子类指定具体类型”的目标。
内容的提问来源于stack exchange,提问作者8bitjunkie

