绑定两个泛型类型

时间:2012-03-07 09:11:22

标签: java generics interface abstract-class

我对泛型有疑问。 我有以下界面:

public interface InterfaceA<B extends InterfaceA.InterfaceB> {

    public interface InterfaceB<A extends InterfaceA> {

        void setA(A a);
    }
}

以下InterfaceA的抽象实现:

public abstract class AImplOne<B extends InterfaceA.InterfaceB> implements InterfaceA<B> {

    private final B b;

    public AImplOne(B b) {
        this.b = b;
        b.setA(this); // <-- Unchecked call...
    }
}

我很清楚,调用b.setA(this)未经检查 - 但我不喜欢它,所以我尝试了第二次抽象实现:

public abstract class AImplTwo<A extends InterfaceA, B extends InterfaceA.InterfaceB<A>> implements InterfaceA<B> {

    private final B b;

    public AImplTwo(B b) {
        this.b = b;
        b.setA((A)this); // <-- Unchecked cast
    }
}

再次,我清楚地知道,电话b.setA((A)this)是一个未经检查的演员。

但是如何实现或重新设计它以摆脱未经检查的代码?

1 个答案:

答案 0 :(得分:2)

你实际上有一个相互递归的泛型定义,你可以通过使用原始类型来打破:在

b.setA((A)this); // <- Unchecked cast

this的类型为InterfaceA<? extends InterfaceA.InterfaceB<? extends InterfaceA>>,但其类型应为InterfaceA<? extends InterfaceA.InterfaceB<? extends InterfaceA<? extends InterfaceA.InterfaceB<...>>>>。您将不得不使用

public interface InterfaceA<B extends InterfaceA.InterfaceB<?>> {

    public interface InterfaceB<A extends InterfaceA<B>> { //<- cannot make a static reference to the non-static type B

        void setA(A a);
    }
}

但是你不能在静态接口声明中使用非静态的B(接口声明总是静态的)。


详细信息,请进一步尝试:使用备选方案

public interface InterfaceA<B extends InterfaceA.InterfaceB<?>> {

    public interface InterfaceB<A extends InterfaceA<? extends InterfaceA.InterfaceB<?>>> {

        void setA(A a);
    }
}


abstract class AImplTwo<B extends InterfaceA.InterfaceB<A>, A extends InterfaceA<B>> implements InterfaceA<B> {

    private final B b;

    public AImplTwo(B b) {
        this.b = b;
        b.setA((A)this); // <-- Unchecked cast
    }
}

再次导致未经检查的强制转换,因为现在InterfaceAinterface InterfaceB<A extends InterfaceA<? extends InterfaceA.InterfaceB<?>>>的嵌套类型参数又是InterfaceA.InterfaceB<?>的任意子类。


更新,因为您要求进行一般设计:

我认为InterfaceB(实际上是一般的接口)是具体实现的抽象:在InterfaceA的实现中,您只需要接口InterfaceB,而不是它的实现细节。将InterfaceB视为合同,您不关心实现。因此,不需要将InterfaceA的实现绑定到InterfaceB的实现:

public interface InterfaceA {

    public interface InterfaceB {

        void setA(InterfaceA a);
    }
}

只有由于我无法看到的原因,您确实希望所使用的InterfaceB的所有实例具有相同的类型,您才需要泛型。对于InterfaceA,反之亦然。使用上面的最后一个泛型示例,您至少可以修复InterfaceA和InterfaceB的类型,并且只需要动态断言A的B和B的A是相同的。

显示Java中不存在类型检查解决方案是困难的,但是可能通过以下示例变得合理,如果Java允许extends和super的组合,这将是一个解决方案:

public interface A<TB extends A.B<?>> {

    public interface B<TA extends A<? extends A.B<?>>> {

        void setA(TA a);
    }
}


class AImplTwo<TB extends A.B<TA>, TA extends AImplTwo<TB, TA> super AImplTwo<TB, TA>> implements A<TB> {

    private final TB b;

    public AImplTwo(TB b) {
        this.b = b;
        b.setA((TA)this);
    }
}

...想到它,可插入类型系统,它为Java添加了更多类型,允许扩展和超级的这种组合,因此可能为您的问题提供解决方案。但是我发现它太复杂了你得到的东西,并且要么坚持使用没有泛型的接口或一些未经检查的演员。