我有一个抽象的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
EmailAccount
是MonitorAccount
的一个子类,所以(至少在我看来)以这种方式覆盖它是完全合理的。但是,鉴于编译器对我的逻辑不满意,我应该如何正确地执行此操作,同时仍然保持编译时检查,以确保对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、等,其将接收/发送原始列表,然后不得不强制其为所需类型,从而导致潜在的运行时类型转换异常。