当前位置: 首页 > 面试题库 >

涉及继承的Java泛型

苏品
2023-03-14
问题内容

我有一个(对我而言)复杂的Java泛型问题。我通读了一些文档,并了解了一些,但不是全部。基本上,对我来说,尝试解决它会导致尝试和错误。

在下文中,我给出了代码的精简示例,一次没有任何泛型(这样一个人就可以希望理解我想要实现的目标),而另一个则有一些更接近解决方案的补充。请更正我的第二个版本和/或指向特定的文档。(我有Java泛型的常规文档。但是我的代码似乎遇到了一些干扰性的挑战,因此很难找到正确的解决方案)

关于我的示例:有一个抽象的基本类型和几个实现的变体(仅给出一个)。方法combine()调用getOp1(),它决定(取决于<some condition>)是应该对自己的实例还是对新实例进行操作。计算后,它将返回目标实例。

abstract class Base {
    protected final Base getOp1() {
        if(Util.isConditionMet()) { return getNewInstance(); }
        else { return this; }
    }
    protected abstract Base getNewInstance(); // returns a new instance of an implementing class
    public abstract Base combine(Base other);
}

class Variant extends Base {
    public Variant getNewInstance() { return new Variant(); }   
    public combine(Variant op2) {
        Variant op1 = getOp1();
        op1.calculate(op2);
        return op1;
    }
    private void calculate(Variant other) { /* some code */ }
}

添加了一些泛型的版本。该版本有故障,无法编译。

abstract class Base<T extends Base<T>> {
    protected final T getOp1() {
         if(Util.isConditionMet()) { return getNewInstance(); }
         else { return this; }
    }
    protected abstract T getNewInstance(); // returns a new instance of an implementing class
    public abstract T combine(T other);
}

class Variant<T extends Variant<T>> extends Base<T> {
    protected T getNewInstance() { return new Variant(); }  
    public T combine(T op2) {
        T op1 = getOp1();
        op1.calculate(op2);
        return op1;
    }
    private void calculate(T other) { /* some code */ }
}

问题答案:

为了使此代码正常工作,您需要解决不兼容类型的问题:将T返回类型替换为Base<T>,并将结果强制转换Variant#getOp1()Variant<T>以允许对其进行调用calculate()(此处很安全,因为Variant#getOp1()始终返回Variant

abstract class Base<T extends Base<T>> {
    protected final Base<T> getOp1() {
         return condition() ? getNewInstance() : this;
    }
    protected abstract Base<T> getNewInstance(); 
    public abstract Base<T> combine(T other);
}



class Variant<T extends Variant<T>> extends Base<T> {
    protected Base<T> getNewInstance() { 
        return new Variant(); 
    }

    public Base<T> combine(T op2) {
        Variant<T> op1 = (Variant<T>) getOp1();   // <- explicit cast
        op1.calculate(op2);
        return op1;
    }

    private void calculate(Base<T> other) { 
        // ...
    }
}

顺便说一句,我仍然没有看到如此复杂的类型结构的原因。



 类似资料:
  • 问题内容: 当存在内部类时,我很难理解继承在Java中的工作方式。我目前正在处理一些子类需要稍微更改其父类的内部类功能的事情。我在下面提出了一个更简单,类似的示例。 我希望此代码可以打印“我是ChildClass.InnerClass”,但可以打印“我是ParentClass.InnerClass”。为什么是这样?另外,如果我将main中的obj对象更改为ChildClass类型,则输出将更改为“

  • 假设类“X”映射到表“X”,类“A”映射到表“A”,类“B”映射到表“B”。 表X结构:(X\u ID,其他一些列表A结构:(A\u ID,X\u ID,其他一些列)表B结构:(A\u ID,其他一些列)。。。表B也有一个\u Id “B”类扩展了“A”类。我们将它们的映射文件都设置为: “A”类父映射文件: “B”类映射文件: 现在,我有一个SQL查询,如下所示,我需要使用Hibernate标准

  • 我发现的最接近的问题(方法链接:在多级继承的情况下如何使用getThis()技巧)并没有直接回答我的问题。我目前正在使用morphia,正在建立一个rest服务。我已经看过很多版本如何实现这一点,并决定这样做。我完全愿意接受建议,但是,学习如何解决这个问题,将有助于我的编码实践,至少我认为会。此外,我知道我的命名约定可能会被取消,所以我也愿意接受这样的更正:) 这是我的代码: 最终,我希望有一个学

  • 和这个问题相关的课程: 现在,这似乎已被编译器接受。不幸的是,我不知道/理解如何创建的新实例,。 当然,这确实不起作用:

  • 问题内容: 我有三节课: 现在在我的主要职能中,我做这样的事情: 但这会产生2个编译时错误: 无法将A转换为fileHandler 无法将B转换为fileHandler 如果基类不是泛型的,那么我如何摆脱这些错误呢? 更新: 我的班级层次结构是: 调用函数的C类或 调用函数的D类。 C和D都从抽象类E派生。 现在,我应该如何在C和D以及E中定义这些功能: 我给出了以下内容: E: C: D: C,

  • 问题内容: 假设Java具有以下层次结构类: 这是C#中相同代码的(盲)重复: 当我执行Java代码时,我得到了C#返回的信息。 对我来说,C#的结果更有意义,因为引用B调用了它自己的方法。 Java设计者决定打印而不是打印的逻辑是什么?我的意思是,为什么引用B在C中使用覆盖方法?这种方法的优势是什么? 如何更改Java代码以像C#一样打印出来?我的意思是,我怎么教Java调用它使用的完全引用的方