【问题标题】:How to get rid of "Type Safety" warning for generic builder?如何摆脱通用构建器的“类型安全”警告?
【发布时间】:2013-12-01 19:20:41
【问题描述】:

我使用构建器模式和元素和构建器的抽象基类来实现不可变组合。为了减少强制转换的需要并使元素的代码尽可能简洁,我使用泛型创建基类。我收到一个我不明白的警告。请解释为什么显示警告以及如何摆脱它(当然不使用@SuppressWarnings("unchecked"))?

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

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

【问题讨论】:

    标签: java generics


    【解决方案1】:

    问题是你的newBuilder() 方法的B 类型参数没有绑定到任何东西:

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

    此方法签名允许用户指定 anyB extends AbstractBuilder&lt;J, B&gt; 作为返回类型,而不仅仅是:

    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();
    

    【讨论】:

    • 谢谢。您喜欢的解决方案 (2) 对我来说效果很好。
    猜你喜欢
    • 2023-03-06
    • 2018-07-19
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    相关资源
    最近更新 更多