如何摆脱通用生成器的“类型安全”警告?

时间:2013-12-01 19:20:42

标签: java generics

我使用构建器模式和元素和构建器的抽象基类实现了一个不可变的组合。为了减少转换的需要并尽可能简洁地获取元素的代码,我使用泛型创建基类。我得到一个警告我不会理解。请解释为什么警告显示以及我如何摆脱警告(当然没有使用@SuppressWarnings(“未经检查”))?

以下是我的代码的相关部分:

abstract public class JElement<J extends JElement<J>> {
    abstract protected <B extends AbstractBuilder<J, B>> B newBuilder();

    abstract public static class AbstractBuilder<J extends JElement<J>, B extends AbstractBuilder<J, B>> {

        public AbstractBuilder() {
        }

        abstract public J build();
    }
}

public class JClass extends JElement<JClass> {
    JClass(Builder builder) {
    }

    @Override
    protected Builder newBuilder() {
        return new Builder(this);
    }

    public static class Builder extends JElement.AbstractBuilder<JClass, Builder> {
        public Builder(JClass jClass) {
        }

        @Override
        public JClass build() {
            return new JClass(this);
        }
    }
}

警告位于JClass.newBuilder的返回值:

  

类型安全:来自的newBuilder()的返回类型JClass.Builder   类型JClass需要未经检查的转换以符合类型中的B.   JElement

1 个答案:

答案 0 :(得分:2)

问题是B方法的newBuilder()类型参数未绑定到任何内容:

abstract protected <B extends AbstractBuilder<J, B>> B newBuilder();

此方法签名允许用户将任何B extends AbstractBuilder<J, B>指定为返回类型,而不仅仅是:

public static class Builder extends JElement.AbstractBuilder<JClass, Builder> {

您定义的类。这个问题有两个有效的解决方案:

1)在B的类定义中将J绑定到J,方法是将声明更改为:

 abstract public class JElement<J extends JElement<J>, B extends JElement.AbstractBuilder<J, B>> {

2)我首选的解决方案,将抽象方法签名更改为:

 abstract protected AbstractBuilder<J, ?> newBuilder();