我有一个(对我而言)复杂的Java泛型问题。我通读了一些文档,并了解了一些,但不是全部。基本上,对我来说,尝试解决它会导致尝试和错误。
在下文中,我给出了代码的精简示例,一次没有任何泛型(这样一个人就可以希望理解我想要实现的目标),而另一个则有一些更接近解决方案的补充。请更正我的第二个版本和/或指向特定的文档。(我有Java泛型的常规文档。但是我的代码似乎遇到了一些干扰性的挑战,因此很难找到正确的解决方案)
关于我的示例:有一个抽象的基本类型和几个实现的变体(仅给出一个)。方法combine()调用getOp1(),它决定(取决于<some condition>)是应该对自己的实例还是对新实例进行操作。计算后,它将返回目标实例。
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:
T
Base<T>
Variant#getOp1()
Variant<T>
calculate()
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) { // ... } }
顺便说一句,我仍然没有看到如此复杂的类型结构的原因。