Java 泛型 - 接受 <? 的方法不允许使用 T 类型的对象。延伸 T>

标签 java generics

在下面的示例中,编译器在线上提示: 处理程序.handle(信息);出现错误:

The method handle(capture#3-of ? extends T) in the type Event.Handler is not applicable for the arguments (T)

即使本例中的 Handler 被声明为接受 T 的任何子类,编译器也不会接受类型 T 本身的方法调用。

public class Event<T> {
    public interface Handler<U> {
        public void handle(U info);
    }

    private final Handler<? extends T> handler;
    private final T info;

    public Event(Handler<? extends T> handler, T info) {
        this.handler = handler;
        this.info = info;
    }

    public void doEvent() {
        handler.handle(info);
    }
}

此示例的另一个有趣的功能是如果您键入:“handler”。在 Eclipse 中给出以下建议“handle(null info): void”。不知何故,类型“null”被建议作为可接受的类型。

从命令行使用 javac 编译仍然会产生类似的错误,因此这不仅仅是 Eclipse 的问题。

我的问题:

  1. 这是 java 编译器的正确行为吗?
  2. 如果这是正确的行为,我应该采取什么措施来保持事件类的类型安全?
  3. 什么是 null 类型?

最佳答案

它被声明为扩展 T 的某种类型的处理程序。假设 T 是对象,并且您传入 Handler<String> 。从构造函数的角度来看这很好 - 但你不会期望能够调用 handler.handle(new Object())你会?一个Handler<String>应该只处理字符串,而不是任意对象。

基本上,您正在寻找逆变而不是协变,因此您需要:

private final Handler<? super T> handler;
private final T info;

public Event(Handler<? super T> handler, T info) {
    this.handler = handler;
    this.info = info;
}

关于Java 泛型 - 接受 <? 的方法不允许使用 T 类型的对象。延伸 T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6611780/

相关文章:

java - 需要连接的 hibernate 路径,但路径已设置

java - JUnit RemoteTestRunner NoClassDefFoundError Junit4 Eclipse 3.7.2

java - 如何在用户所在的当前目录中打开 JFileChooser?

java - 方法的泛型重载 - 解决方法

c# - 无效泛型类型参数的最佳异常(exception)

c# - XML反序列化泛型方法

java - 打印字符串中使字符串与正则表达式匹配的部分

java - 直接在 Treeset 中添加元素与从 arraylist 传输元素的性能有何差异?

c++ - 需要 C++ 中非常通用的 argmax 函数

java - 编译时的工厂模式