我对泛型有疑问。 我有以下界面:
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)
是一个未经检查的演员。
但是如何实现或重新设计它以摆脱未经检查的代码?
答案 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
}
}
再次导致未经检查的强制转换,因为现在InterfaceA
中interface 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添加了更多类型,允许扩展和超级的这种组合,因此可能为您的问题提供解决方案。但是我发现它太复杂了你得到的东西,并且要么坚持使用没有泛型的接口或一些未经检查的演员。