java - 实现其中包含其他通用定义的原始接口(interface)

标签 java generics type-erasure raw-types

给定以下接口(interface)和类:

public interface Interface<T> {
    List<T> get(List<List<Object>> keys);
}

public class Cls implements Interface {
    @Override
    public List get(List<List<Object>> keys) {
        return Collections.emptyList();
    }
}

导致编译错误:

TypeTest.java:[9,11] error: Cls is not abstract and does not override abstract method get(List) in Interface
TypeTest.java:[12,20] error: name clash: get(List<List<Object>>) in Cls and get(List<List<Object>>) in Interface have the same erasure, yet neither overrides the other

但这行得通:

public interface Interface<T> {
    List<T> get();
}

public class Cls implements Interface {
    @Override
    public List get() {
        return Collections.emptyList();
    }
}

这样做:

public interface Interface<T> {
    List<T> get(List<List<Object>> keys);
}

public class Cls implements Interface {
    @Override
    public List get(List keys) {
        return Collections.emptyList();
    }
}

我不明白这种行为。类型删除仅适用于类型参数 T ,不是吗?为什么会漏掉 T影响不相关List<List<Object>> keys参数?

最佳答案

由于原始类型发生类型删除,您在第一个示例中遇到编译器错误。 Section 4.8 of the JLS描述了使用原始类型会产生类型删除的情况:

To facilitate interfacing with non-generic legacy code, it is possible to use as a type the erasure (§4.6) of a parameterized type (§4.5) or the erasure of an array type (§10.1) whose element type is a parameterized type. Such a type is called a raw type.

The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of its parameterized invocations.

本节中的其他条款还描述了字段类型、方法的返回类型和方法的参数类型如何也受到类型删除的影响。

继续 Section 4.6 of the JLS ,如上所述:

The type parameters of a constructor or method (§8.4.4), and the return type (§8.4.5) of a method, also undergo erasure if the constructor or method's signature is erased.

因此,删除的方法get

List get(List);

您的初始示例将无法编译,因为 Cls' 的方法签名s get方法,get(List<List<Object>>)不匹配原始接口(interface)的方法,也没有实现原始接口(interface)的get方法。

这也是您的第二个和第三个示例编译的原因——它们正确地覆盖了原始接口(interface) Interface .

顺便说一下,要覆盖通用的 Interface接口(interface)而不求助于实现原始类型,在 implements 中提供一个类型参数子句:

public interface Interface<T> {
    List<T> get(List<List<Object>> keys);
}

实现它:

class Cls<T> implements Interface<T> {
    @Override
    public List<T> get(List<List<Object>> keys) {
        return Collections.emptyList();
    }
}

或者

class Cls implements Interface<String> {
    @Override
    public List<String> get(List<List<Object>> keys) {
        return Collections.emptyList();
    }
}

任何引用类型都适用于 implements Interface<String> , 只要类型匹配 get 中的返回类型.子句implements Interface<Integer>将使用方法 List<Integer> get(List<List<Object>> keys) .

简而言之,类型删除发生在原始类/接口(interface)中的所有参数化类型和泛型类型,无论它们是否与类/接口(interface)上声明的泛型类型参数相关。

关于java - 实现其中包含其他通用定义的原始接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20373692/

相关文章:

java - Java 中可比较接口(interface)与通用静态方法的使用

java - 如果我们应用类型删除,哪些重载方法将在运行时被调用,为什么?

scala - 在 Akka 中保留类型参数接收

java - 如何在等待长 POST 请求时显示进度/请等待类型组件

swift - 在 Swift 中重载泛型函数时出现 "Ambiguos use of function"

java - 使用 Stanford CoreNLP 的段落中断

Java泛型——获取泛型参数的实际类型

java - 为什么在 Java 中无法对已删除类型进行拆箱?

java - ECDH 服务器 key 交换消息上的签名无效

Java:Windows 7 外观(或 MouseListener?)需要在 JOptionPane 上单击两次