Java 为什么这个方法调用失败?(泛型和通配符)
我得到以下错误:Java 为什么这个方法调用失败?(泛型和通配符),java,generics,extends,Java,Generics,Extends,我得到以下错误: 'call(ContainsMonitor)' cannot invoke 'call(? extends webscout.Monitor)' in 'WebScoutCallable' Monitor.java WebScoutCallable<? extends Monitor> handler; public setCallable(WebScoutCallable<? extends Monitor> callable) { th
'call(ContainsMonitor)' cannot invoke 'call(? extends webscout.Monitor)' in 'WebScoutCallable'
Monitor.java
WebScoutCallable<? extends Monitor> handler;
public setCallable(WebScoutCallable<? extends Monitor> callable) {
this.handler = callable;
}
public class ContainsMonitor extends Monitor {
public void handleDocument() {
handler.call(this);
}
}
我可以坦率地承认,我是泛型新手,而且对Java本身还是相当陌生的。我发现错误消息令人困惑,因为它看起来应该可以工作(方法声明需要一个监视器或子类,我正在传递一个子类)。任何帮助(+解释)将不胜感激
谢谢
?扩展监视器
的意思是:监视器的一个特定子类,但我们不知道是哪个子类。因此,它可能是ContainsMonitor
或不是handler
可能无法接受ContainsMonitor
。编译器无法决定并显示错误
解决问题的一种方法是使用特定类型,例如:
class Monitor<T extends Monitor<T>> {
WebScoutCallable<T> handler;
public setCallable(WebScoutCallable<T> callable) {
this.handler = callable;
}
}
class ContainsMonitor extends Monitor<ContainsMonitor> {
public void handleDocument() {
handler.call(this);
}
}
类监视器{
WebScoutCallable处理器;
公共设置可调用(WebScoutCallable可调用){
this.handler=callable;
}
}
类ContainsMonitor扩展了监视器{
公共无效处理文件(){
handler.call(this);
}
}
在处理程序的类型参数中有一个通配符。编译器不知道此类型参数的确切类型,只知道它是Monitor
或子类
call
方法采用一个在通配符上匹配的T
。但不能保证通配符类型是ContainsMonitor
。它可以是监视器
,也可以是监视器子系统,但不属于纺织商
。因为编译器不知道实际的类型,所以它不能允许您传递除null
之外的任何内容,因为对于任何非null
参数,它不能保证类型安全
您可以通过删除通配符,并在监视器
类中将该概念替换为类型参数来解决这个问题
class Monitor<T extends Monitor<T>>
{
WebScoutCallable<T> handler;
public void setCallable(WebScoutCallable<T> callable) {
this.handler = callable;
}
}
扩展监视器时,子类将自己的名称作为类型参数提供
class ContainsMonitor extends Monitor<ContainsMonitor> {
public void handleDocument() {
handler.call(this);
}
}
类ContainsMonitor扩展了监视器{
公共无效处理文件(){
handler.call(this);
}
}
现在,T
将是一个已知的类型,ContainsMonitor
将其定义为自身,因此现在将其自身传递给call
是合法的。您的代码不需要泛型
public class Monitor {
WebScoutCallable handler;
public void setCallable(WebScoutCallable callable) {
this.handler = callable;
}
}
public interface WebScoutCallable {
public void call(Monitor caller);
}
public class ContainsMonitor extends Monitor {
public void handleDocument() {
handler.call(this);
}
}
这并没有回答OP的问题谢谢你的详细回答。我认为可能会有一个不那么冗长的解决方案,但这是有道理的!谢谢你的快速回复。但愿我能将两种解决方案标记为正确!
class ContainsMonitor extends Monitor<ContainsMonitor> {
public void handleDocument() {
handler.call(this);
}
}
public class Monitor {
WebScoutCallable handler;
public void setCallable(WebScoutCallable callable) {
this.handler = callable;
}
}
public interface WebScoutCallable {
public void call(Monitor caller);
}
public class ContainsMonitor extends Monitor {
public void handleDocument() {
handler.call(this);
}
}