为什么此方法调用失败? (泛型和通配符)

我收到以下错误:

'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或子类,我正在传递一个子类)。 任何帮助(+解释)将不胜感激!

谢谢!


您的handler变量的类型参数中有一个通配符。 编译器不知道这个类型参数的确切类型,只是它是Monitor或一个子类。

call方法需要一个T ,它在通配符上匹配。 但是不能保证通配符类型是ContainsMonitor 。 它可能是一个Monitor ,或者它可能是MonitorSubtypeThatDoesntExistYet 。 因为编译器不知道实际的类型,所以它不能让你传递除null之外的任何东西,因为对于任何非null参数,它不能保证类型安全。

您可以通过删除通配符来解决此问题,并使用Monitor类中的类型参数替换该概念。

class Monitor<T extends Monitor<T>>
{
    WebScoutCallable<T> handler;

    public void setCallable(WebScoutCallable<T> callable) {
         this.handler = callable;
    }
}

WebScoutCallable接口的响应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将它定义为它自己,所以它现在是合法的,它将自己传递给call


? extends Monitor ? extends Monitor意思是: ? extends Monitor一个特定的子类,但我们不知道哪一个。 因此它可能是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);
  }
}

你的代码不需要泛型。

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);
     }
}
链接地址: http://www.djcxy.com/p/85839.html

上一篇: Why does this method call fail? (Generics & wildcards)

下一篇: How to check a value like "#define VERSION 3.1.4" at compile time?