用Java中的泛型参数覆盖方法?

时间:2008-10-27 11:46:58

标签: java generics inheritance

我有一个抽象类 Monitor.java ,它由Class EmailMonitor.java 子类化。

方法:

public abstract List<? extends MonitorAccount> performMonitor(List<? extends MonitorAccount> accounts)

Monitor.java 中定义,必须在 EmailMonitor.java 中重写。

我目前在 EmailMonitor.java 中重写方法如下:

@Override
public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
    //...unrelated logic
    return emailAccounts;
}

但是,这会产生编译时错误:

Name clash: The method performMonitor(List<EmailAccount>) of type EmailMonitor has the same erasure as performMonitor(Lis<? extends MonitorAccount> emailAccounts) of type Monitor but does not override it

EmailAccountMonitorAccount的子类,因此(至少在我看来)以这种方式覆盖它是完全合理的。虽然看起来编译器对我的逻辑不满意,但是如何在保持编译时检查的同时正确地解决这个问题,以确保对EmailMonitor.performMonitor()的所有调用都收到EmailAccount的列表而不是其他一些列表MonitorAccount的类型?

2 个答案:

答案 0 :(得分:34)

不,它没有正确地覆盖它。覆盖意味着您应该能够处理基类的任何有效输入。考虑如果客户这样做会发生什么:

Monitor x = new EmailMonitor();
List<NonEmailAccount> nonEmailAccounts = ...;
x.performMonitor(nonEmailAccounts);

根据你的描述,那里没有什么应该给出编译时错误 - 但这显然是错误的。

我觉得Monitor在其可以监控的帐户类型中应该是通用的,因此EmailMonitor应该扩展Monitor<EmailAccount>。所以:

public abtract class Monitor<T extends MonitorAccount>
{
    ...
    public abstract List<? extends T> performMonitor(
        List<? extends T> accounts);
}

public class EmailMonitor extends Monitor<EmailAccount>
{
    @Override
    public abstract List<? extends EmailAccount> performMonitor(
        List<? extends EmailAccount> accounts)
    {
        // Code goes here
    }
}

你可能想仔细考虑performMonitor电话中的泛型 - 返回值意味着什么?

答案 1 :(得分:9)

这是我自己的解决方案。我怀疑这与Jon Skeet试图达到的目标相同......没有错字(请参阅我的评论回复他的回答)。

Monitor.java 类:

public abstract class Monitor <T extends MonitorAccount> {
  ...
  public abstract List<T> performMonitor(List<T> accounts);
  ..
}

EmailMonitor.java

public class EmailMonitor extends Monitor<EmailAccount> {
  ...
  public List<EmailAccount> performMonitor(List<EmailAccount> emailAccounts) {
    ..//logic...logic...logic
    return emailAccounts;
  }
  ...
}

在此配置中, EmailMonitor.performMonitor()将始终在编译时检查它是否收到 EmailAccount 的列表而不是我的任何其他类型 FTPAccount ,DBAccount,等......它比替代方案更清晰,它本来是接收/发送原始列表,然后必须强制它所需的类型,导致潜在的运行时类型转换异常。