我可以在Java中使用自绑定泛型和子类避免这种未经检查的强制转换吗?

我可以在Java中使用自绑定泛型和子类避免这种未经检查的强制转换吗?,java,generics,Java,Generics,我知道SO中有很多类似的问题,但我恐怕找不到类似的例子。请原谅我,如果有一个(我希望有一个链接:) 我有两个基类,具有自界泛型: public interface View<V extends View<V, P>, P extends Presenter<V, P>> { P getPresenter(); } public abstract class Presenter<V extends View<V, P>, P exte

我知道SO中有很多类似的问题,但我恐怕找不到类似的例子。请原谅我,如果有一个(我希望有一个链接:)

我有两个基类,具有自界泛型:

public interface View<V extends View<V, P>, P extends Presenter<V, P>> {
    P getPresenter();
}

public abstract class Presenter<V extends View<V, P>, P extends Presenter<V, P>> {
    protected V view;

    public void takeView(V view) { this.view = view; }
}
有趣的是,如果我不在BaseView中调用takeView,并且在每个具体实现中都这样做,它会再次工作

public class BarView implements BaseView<BarView, FooPresenter> {
    @Override
    public FooPresenter getPresenter() {
        FooPresenter p = createPresenter();
        p.takeView(this); // javac likes this :/
        return p;
    }
}
公共类BarView实现BaseView{
@凌驾
公共FooPresenter getPresenter(){
FooPresenter p=createPresenter();
p、 takeView(这个);//javac喜欢这样:/
返回p;
}
}
有没有办法避免未经检查的强制转换?我认为这是Java泛型的一个限制,但我可能是有限的D


非常感谢。

这将使您的类紧密地联系在一起,因为它似乎只能执行双重分派。我认为你正在触及泛型可以用它做什么的边界,但是你可以用不同的方式实现同样的目标

因此,这不是对您问题的直接回答,而是一种可能的替代方法:

public static abstract class Presenter<V extends View> implements ViewTaker<V> {
    protected V view;

    public void takeView(V view) { this.view = view; }
}

public interface View { // can be a class as well
}

public interface ViewTaker <V extends View> {
    public void takeView(V view);
}
公共静态抽象类Presenter实现了ViewTaker{
保护V型视图;
public void takeView(V view){this.view=view;}
}
公共接口视图{//也可以是类
}
公共界面取景器{
公众观点(V观点);
}
在第二次阅读代码时,您可以使用视图创建它的演示者。这可能是伪代码的局限性,但对我来说这似乎是错误的,通常在视图之外构造演示者,并将视图传递给它。(因此上述代码)。您的具体情况可能有所不同,但是您可能需要发布实际代码,而不是伪代码

我试过你的处境,但实际上我也遇到了同样的极限。看起来像

<P extends A<V>, V> 

2 V被视为潜在的不同,尽管它们将被相同的术语取代。到目前为止,我想不出它们会有什么不同的情况,所以你可能会认为它们是指同一个占位符,但我想这是没有办法的

我建议在你的视野之外重新设计和构建你的演示者。这样,演示者就可以毫无疑问地了解视图(见上文)。 或者,使用pojo版本的视图从视图构造演示者。(视图构造对象,将其馈送给演示者)。如果您只需要呈现一个静态版本,这就可以工作。然后演示者不知道视图,但知道这种表示

有没有办法避免未经检查的强制转换

不,因为演员阵容不安全

考虑以下满足边界的情况:

class FooView extends BaseView<FooView, FooPresenter>
class BarView extends BaseView<FooView, FooPresenter>
然后编译器会抱怨传递
这个


您可以通过向
BaseView
添加一个抽象方法来获得
V
类型的值,从而避免强制转换并使其安全:

abstract public V getView();
每一次实施都必须实施这一点;对于本身就是
V
的类,例如
FooView
,则可以只
返回该值

class FooView extends BaseView<FooView, FooPresenter> {
    public FooView getView() { return this; }
}

您是否尝试过将强制转换与泛型一起使用?e、 g.p.takeView((V)它没有编译:“类型‘V’没有类型参数”。谢谢你的主意!如果未在抽象类中强制转换为V,则错误消息是什么?FooPresenter中的takeView无法应用于View。我的类名不同,所以我把我的代码翻译成他的例子。我认为这不可能发生,因为我使类型自绑定。。。但我错了!我以为这个习语是用来避免这个问题的,现在我只是感到困惑。有没有办法使这个声明不可能?@Serandel:没有,没有办法用Java来声明它。为了进一步澄清(并进一步证明@newacct是完全正确的),我在下面的一段中发现:注意,这并不能阻止您创建使用类型参数的奇怪类型,而类型参数本身是可以的,但这不是同一种类型。其目的是在正确的情况下提供好处,而不是保护您免受错误情况的影响。您是绝对正确的,演示者不是在那里创建的,它只是为了一个最低限度的示例。事实上,创建BaseView是为了从自定义Dagger作用域中注入演示者。。。谢谢你的帮助。
class FooView extends BaseView<FooView, FooPresenter>
class BarView extends BaseView<FooView, FooPresenter>
class BarView implements BaseView<FooView, FooPresenter>
abstract public V getView();
class FooView extends BaseView<FooView, FooPresenter> {
    public FooView getView() { return this; }
}
public P getPresenter() {
    P p = createPresenter();
    p.takeView(getView());
    return p;
}