用Java中的泛型参数重写方法



我有一个抽象的classMonitor.java,它由classEmailMonitor.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

不,它没有正确地覆盖它。重写意味着您应该能够处理基类的任何有效输入。考虑一下如果客户这样做会发生什么:
Monitor x = new EmailMonitor();
List<NonEmailAccount> nonEmailAccounts = ...;
x.performMonitor(nonEmailAccounts);

根据您的描述,其中没有任何内容会导致编译时错误,但这显然是错误的。

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

public abstract 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调用中的泛型——返回值意味着什么?

这是我自己的解决方案。我怀疑这和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、等,其将接收/发送原始列表,然后不得不强制其为所需类型,从而导致潜在的运行时类型转换异常。

最新更新