【问题标题】:Overriding a method with Generic Parameters in Java?用Java中的通用参数覆盖方法?
【发布时间】:2010-09-19 08:56:37
【问题描述】:

我有一个抽象类 Monitor.java,它是一个类 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&lt;EmailAccount&gt;) of type EmailMonitor has the same erasure as performMonitor(Lis&lt;? extends MonitorAccount&gt; emailAccounts) of type Monitor but does not override it

EmailAccountMonitorAccount 的子类,因此(至少在我看来)以这种方式覆盖它非常有意义。看到编译器对我的逻辑不满意,我应该如何正确处理这个问题,同时仍然保持我的编译时间检查以确保所有对EmailMonitor.performMonitor() 的调用都接收EmailAccount 的列表而不是其他类型的@987654328 @?

【问题讨论】:

    标签: java generics inheritance


    【解决方案1】:

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

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

    根据您的描述,其中没有任何内容应该给出编译时错误 - 但它显然是错误的。

    在我看来,Monitor 在它可以监控的帐户类型中应该是通用的,因此您的 EmailMonitor 应该扩展 Monitor&lt;EmailAccount&gt;。所以:

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

    【讨论】:

    • 你说'列表'。现在我根本无法通过 EmailAccount;那是错字吗?我想检查 EmailMonitor 是否始终接收 EmailAccount 列表并始终返回可以在没有动态转换的情况下使用的 EmailAccount 列表。现在发布我的解决方案:)
    【解决方案2】:

    这是我自己的解决方案。我怀疑这与 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, 等...它比替代方案要干净得多,后者本来是接收/发送原始列表,然后必须强制它为所需的类型,从而导致潜在的运行时类型转换异常。

    【讨论】:

    • EmailMonitor 不扩展 MonitorAccount
    猜你喜欢
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    相关资源
    最近更新 更多