我有一个父类Builder,可以使用Builder类型或其子类型的参数来生成它:

class Builder<T extends Builder> {

    @SuppressWarnings("unchecked")
    T doSmth() {
        System.out.println("do smth");
        return (T)this;
    }
}


它有一个子类-BuilderChild

class BuilderChild extends Builder<BuilderChild> {

    BuilderChild doSmthElse() {
        System.out.println("do smth else");
        return this;
    }
}


因此,我可以在doSmth实例上调用方法BuilderChild并返回BuilderChild

new BuilderChild().doSmth().doSmthElse();


但是,当我尝试生成BuilderChild时,上面的行停止了编译。

class BuilderChild<T> extends Builder<BuilderChild> {

    BuilderChild doSmthElse() {
        System.out.println("do smth else");
        return this;
    }
}
...
//Compile error, because doSmth()
//returns Builder instead of BuilderChild.
new BuilderChild().doSmth().doSmthElse();


有人可以解释为什么我生成doSmth()Builder开始返回BuilderChild吗?有什么办法可以解决?

最佳答案

问题是您将BuilderChild用作原始类型。

这意味着它具有类型参数,但是您在不提供任何类型参数的情况下指定了它。

这意味着几乎所有该类型的泛型信息都将被忽略(它是a bit more complicated than that,但这是高级视图)。

如果您改写以下代码:

new BuilderChild<Object>().doSmth().doSmthElse();


然后编译。

另外,doSmthElse应指定为BuilderChild<T> doSmthElse()

请注意,仅支持原始类型是为了向后兼容,而不应在新代码中使用。

09-09 21:27