我收到以下错误:
'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; }
WebScoutCallable.java
public interface WebScoutCallable<T extends Monitor> { public void call(T caller); }
ContainsMonitor.java
public class ContainsMonitor extends Monitor { public void handleDocument() { handler.call(this); } }
我会自由地承认,我对于泛型并不熟悉Java本身.我发现错误消息令人困惑,因为它看起来应该工作(方法声明需要一个Monitor或子类,我传入一个子类).任何帮助(解释)将不胜感激!
谢谢!
解决方法
您的处理程序变量的type参数中有一个通配符.编译器不知道这个类型参数的确切类型是什么,只是它是Monitor或子类.
call方法采用T,在通配符上匹配.但是不能保证通配符类型是ContainsMonitor.它可以是一个监视器,也可以是MonitorSubtypeThatDoesntExistYet.因为编译器不知道实际类型,所以它不允许传递除null之外的任何内容,因为对于任何非null参数,它不能保证类型安全.
您可以通过删除通配符来解决此问题,并使用Monitor类上的类型参数替换该概念.
class Monitor<T extends Monitor<T>> { WebScoutCallable<T> handler; public void setCallable(WebScoutCallable<T> callable) { this.handler = callable; } }
接口WebScoutCallable在响应中稍有变化:
interface WebScoutCallable<T extends Monitor<T>> { public void call(T caller); }
在扩展Monitor时,子类将自己的名称作为类型参数提供.
class ContainsMonitor extends Monitor<ContainsMonitor> { public void handleDocument() { handler.call(this); } }
现在,T将是一个已知的类型,而ContainsMonitor将它定义为它自己,所以现在将它自己传递给调用是合法的.