Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.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 - Fatal编程技术网

Java 为什么我不能用类的实现作为参数重写方法

Java 为什么我不能用类的实现作为参数重写方法,java,generics,Java,Generics,我有简单的抽象结构 public abstract class Data<A extends Serializable> { } 公共抽象类数据{ } 然后是这个类的字符串实现 public class StringData extends Data<String> { } 公共类StringData扩展数据{ } 然后我有一个接口: public interface Testicek<A extends Serializable> {

我有简单的抽象结构

public abstract class Data<A extends Serializable> {

}
公共抽象类数据{
}
然后是这个类的字符串实现

public class StringData extends Data<String> {

}
公共类StringData扩展数据{
}
然后我有一个接口:

public interface Testicek<A extends Serializable> {

    public abstract Data<A> test(Data<A> bla);

}
公共接口测试{
公开摘要数据测试(数据bla);
}
现在我想创建实现此接口的类:

public class TesticekImpl implements Testicek<String> {


    // OK
    @Override
    public StringData test(Data<String> bla) {
        return null;
    }

    // compilation error
    //@Override
    //public StringData test(StringData bla) {
    //    return null;
    //}

}
public interface Testicek<A extends Serializable, D extends Data<A>> {

    public abstract D test(D bla);

}
公共类TesticekImpl实现Testicek{
//嗯
@凌驾
公共数据测试(数据bla){
返回null;
}
//编译错误
//@凌驾
//公共StringData测试(StringData bla){
//返回null;
//}
}
为什么我不能使用我的StringData类作为参数,而它只在返回类型中工作?返回类型和参数的签名是相同的。

public interface Testicek,这意味着接口的实现可以返回比父接口更具体的类型,因为那些更具体的类型仍然是不太具体的类型的实例,因此它们符合接口的约定

public interface Testicek<A extends Serializable> {

    public abstract Data<A> test(Data<A> bla);

}
但是,您不能使用更具体的参数类型,因为接口的约定规定它必须接受该类型的任何实例

子类告诉我们,子类必须接受没有更多限制的参数,并且必须返回没有更多通用性的值

Java不允许您使用“限制较少”的参数类型,因为(这已经相当复杂)。从理论的角度来看,这是不必要的限制,但从实践的角度来看更简单

在接受和返回相同类型方面:在接口中声明另一个类型变量:

public class TesticekImpl implements Testicek<String> {


    // OK
    @Override
    public StringData test(Data<String> bla) {
        return null;
    }

    // compilation error
    //@Override
    //public StringData test(StringData bla) {
    //    return null;
    //}

}
public interface Testicek<A extends Serializable, D extends Data<A>> {

    public abstract D test(D bla);

}
公共接口测试{
公开摘要D检验(D bla);
}
然后,您的实现可以是:

public class TesticekImpl implements Testicek<String, StringData> {
    @Override
    public StringData test(StringData bla) {
        return null;
    }
}
公共类TesticekImpl实现Testicek{
@凌驾
公共StringData测试(StringData bla){
返回null;
}
}

因为实现Testicek的事实要求您必须接受任何数据类型的对象。StringData只是无数数据子类型中的一种。这还不够。您必须接受所有这些,否则您就是没有实现接口。接口声称它接受所有这些。您可以返回StringData,因为您可以返回任何符合数据条件的内容,StringData也可以。@kumesana这看起来像是我的答案。是的,但它在注释中,所以我不能接受:请说您有
类父项{void eat(Fruit t){..}
类子项扩展父项{@override void eat(Apple a){..}
。因为
Child扩展了Parent
我们可以编写
Parent p=newchild()。但是因为
p
属于
Parent
类型,应该支持
eat(Fruit)
我们应该能够安全地调用
p.eat(new Banana())
(其中
Banana
水果的子类型,而不是苹果的
子类型)。那么这里应该发生什么呢?应该调用哪个方法的代码?推翻了对苹果有限的可接受的论点,但家长承诺会处理所有种类的水果。