RNG*_*Guy 7 java generics extends
我收到以下错误:
'call(ContainsMonitor)' cannot invoke 'call(? extends webscout.Monitor)' in 'WebScoutCallable'
Run Code Online (Sandbox Code Playgroud)
Monitor.java
WebScoutCallable<? extends Monitor> handler;
public setCallable(WebScoutCallable<? extends Monitor> callable) {
this.handler = callable;
}
Run Code Online (Sandbox Code Playgroud)
WebScoutCallable.java
public interface WebScoutCallable<T extends Monitor> {
public void call(T caller);
}
Run Code Online (Sandbox Code Playgroud)
ContainsMonitor.java
public class ContainsMonitor extends Monitor {
public void handleDocument() {
handler.call(this);
}
}
Run Code Online (Sandbox Code Playgroud)
我会自由地承认,我对仿制药不熟悉,而且对Java本身来说还是一个新手.我发现错误消息令人困惑,因为它看起来应该工作(方法声明需要一个Monitor或子类,我传入一个子类).任何帮助(+解释)将不胜感激!
谢谢!
您的handler变量的type参数中有一个通配符.编译器不知道这个类型参数的确切类型是什么,只是它是一个Monitor或一个子类.
该call方法采用a T,在通配符上匹配.但是不能保证通配符类型是a ContainsMonitor.它可能是一个Monitor,也可能是MonitorSubtypeThatDoesntExistYet.因为编译器不知道实际类型,所以它不能允许你传递任何东西null,因为任何非null参数都不能保证类型安全.
您可以通过删除通配符来解决此问题,并使用类上的类型参数替换该概念Monitor.
class Monitor<T extends Monitor<T>>
{
WebScoutCallable<T> handler;
public void setCallable(WebScoutCallable<T> callable) {
this.handler = callable;
}
}
Run Code Online (Sandbox Code Playgroud)
界面WebScoutCallable响应稍有变化:
interface WebScoutCallable<T extends Monitor<T>> {
public void call(T caller);
}
Run Code Online (Sandbox Code Playgroud)
扩展时,子类将自己的名称作为类型参数提供Monitor.
class ContainsMonitor extends Monitor<ContainsMonitor> {
public void handleDocument() {
handler.call(this);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,T将是一个已知的类型,并将其ContainsMonitor定义为它自己,所以它现在是合法的,它传递给自己call.