Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 实现包含其他泛型定义的原始接口_Java_Generics_Type Erasure_Raw Types - Fatal编程技术网

Java 实现包含其他泛型定义的原始接口

Java 实现包含其他泛型定义的原始接口,java,generics,type-erasure,raw-types,Java,Generics,Type Erasure,Raw Types,给定以下接口和类: 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

给定以下接口和类:

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();
    }
}
公共接口{
列表获取(列表键);
}
公共类Cls实现接口{
@凌驾
公共列表获取(列表键){
返回集合。emptyList();
}
}
导致编译错误:

TypeTest.java:[9,11]错误:Cls不是抽象的,并且不重写接口中的抽象方法get(List)
java:[12,20]错误:名称冲突:Cls中的get(List)和接口中的get(List)具有相同的擦除,但两者都不重写另一个
但这是可行的:

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

public class Cls implements Interface {
    @Override
    public List get() {
        return Collections.emptyList();
    }
}
公共接口{
List get();
}
公共类Cls实现接口{
@凌驾
公共列表get(){
返回集合。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();
    }
}
公共接口{
列表获取(列表键);
}
公共类Cls实现接口{
@凌驾
公共列表获取(列表键){
返回集合。emptyList();
}
}

我不理解这种行为。类型擦除仅适用于类型参数
T
,不是吗?为什么遗漏
T
会影响不相关的
列表键
参数?

我认为类测试也必须是对象泛型类型。下面是代码工作

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

public class Test<Object> implements Interface<Object> {

    @Override
    public List<Object> get(List<List<Object>> keys) {
        return Collections.emptyList();
    }
}
接口{
列表获取(列表键);
}
公共类测试实现接口{
@凌驾
公共列表获取(列表键){
返回集合。emptyList();
}
}
还有下面

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

public class Test<Object> implements Interface<Object> {

    @Override
    public List<Object> get(List<List<Object>> keys) {
        return Collections.emptyList();
    }
}
接口{
列表获取(列表键);
}
公共类测试实现接口{
@凌驾
公共列表获取(列表键){
返回集合。emptyList();
}
}

在编译时,您试图做的事情有点棘手,参考请参见类似Hashtable的类和搜索类似KeySet的类,这可能会给您一些想法

在第一个示例中,由于原始类型发生类型擦除,因此出现了编译器错误。描述使用原始类型将产生类型擦除的情况:

为了便于与非通用遗留代码接口,可以使用参数化类型(§4.5)的擦除(§4.6)或元素类型为参数化类型的数组类型(§10.1)的擦除作为类型。这种类型称为原始类型

原始类型的超类(分别是超级接口)是对其任何参数化调用的超类(超级接口)的擦除

本节中的其他子句还描述了字段类型、方法的返回类型和方法的参数类型也是如何进行类型擦除的

继续,如上所述:

如果构造函数或方法的签名被删除,则构造函数或方法的类型参数(§8.4.4)和方法的返回类型(§8.4.5)也会被删除

因此,方法
get
的擦除是

List get(List);
您的初始示例将无法编译,因为
Cls'
s
get
method、
get(List)
的方法签名与原始接口的方法不匹配,并且它没有实现原始接口的
get
方法

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

顺便提一下,要在不实现原始类型的情况下重写泛型
接口
接口,请在
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();
    }
}
类Cls实现接口{ @凌驾 公共列表获取(列表键){ 返回集合。emptyList(); } }

类Cls实现接口{ @凌驾 公共列表获取(列表键){ 返回集合。emptyList(); } }
只要类型与
get
中的返回类型匹配,任何引用类型都可以在
implements接口中工作。子句
实现接口
将与方法
List get(List key)
一起使用


简而言之,原始类/接口中的所有参数化类型和泛型类型都会发生类型擦除,而不管它们是否与类/接口上声明的泛型类型参数相关。

为什么不实现
接口
?我使用的框架的限制。我更感兴趣的是试图理解这种奇怪的行为;我已经解决了编译错误。我猜List就是T,所以实现者应该得到的是List
T
List
是完全分开的。这是多键查找接口的简化。
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();
    }
}