我有一个抽象类 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
EmailAccount
是MonitorAccount
的子类,因此(至少在我看来)以这种方式覆盖它是完全合理的。虽然看起来编译器对我的逻辑不满意,但是如何在保持编译时检查的同时正确地解决这个问题,以确保对EmailMonitor.performMonitor()
的所有调用都收到EmailAccount
的列表而不是其他一些列表MonitorAccount
的类型?
答案 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,等......它比替代方案更清晰,它本来是接收/发送原始列表,然后必须强制它所需的类型,导致潜在的运行时类型转换异常。