未经检查的转换警告与泛型

时间:2019-07-03 11:07:49

标签: java generics builder-pattern

我不太清楚,为什么我的代码必须进行未经检查的转换以及如何解决该问题。

我正在使用构建器模式实现不可变对象,为此我使用内部接口“ Builder”实现了“ Immutable”接口。

每个不可变的类都实现Immutable接口,并实现内部的静态类Builder,该类实现了Builder接口。

所有这些都很好。

现在,我正在实现一堆非常简单的类,这些类实际上并不需要构建器,但是我仍然想实现Immutable接口,因此这些类的对象是“ Immutable”的实例,但我不需要不想为每个类实现没有任何功能的空生成器。我宁愿有一个抽象类,在其中为所有简单类实现一个简单的生成器。构建器将只存储原始对象并通过build()方法将其返回,因此Immutable接口已完全实现

尽管如此,构建器的build()方法必须返回实现类的对象。所以我添加了泛型。

public interface Immutable {
    public interface Builder<T> {
        public T build();
    }
    public <T> Builder<T> builder();
}


public interface Interface extends Immutable {

    public interface BuilderInterface<T> extends Immutable.Builder<T> {

    }
}


public abstract class AbstractClass implements Interface {

    public static class AbstractBuilder<T> implements Interface.BuilderInterface<T> {

        private final T object;

        public AbstractBuilder(T object) {

            this.object = object;
        }

        @Override
        public T build() {

            return this.object;
        }
    }

    protected AbstractClass() {

        super();
    }
}

public class ConcreteClass extends AbstractClass {

    public ConcreteClass() {

    }

    @Override
    public AbstractBuilder<ConcreteClass> builder() {

        return new AbstractClass.AbstractBuilder<ConcreteClass>(this);
    }
}

我期望Immutable接口的通用类型T采用实现类的类型,但相反,它似乎是Object,这会导致以下警告:

类型安全:返回的ConcreteClass类型的builder()的abstractClass.AbstractBuilder类型需要未经检查的转换才能符合Immutable类型的Immutable.Builder

编辑:警告由ConcreteClass的builder()方法给出。

1 个答案:

答案 0 :(得分:1)

这非常简单-Immutable#builder的方法签名期望类型参数T为实际方法调用“即时”设置,而不是绑定到类。为了适当地覆盖此方法,ConcreteClass中的符号应为

public <T> Builder<T> builder() {

这显然与您的构建器定义冲突

return new AbstractClass.AbstractBuilder<ConcreteClass>(this);

要使其全部可编译,​​您必须从类而不是方法调用程序中为T推断Immutable#builder,即您最终拥有

public interface Immutable<T> {

    public interface Builder<T> {
        public T build();
    }

    public Builder<T> builder(); 
}

,所有继承的类也进行了相应更改,以将T传递给其前任。

public interface Interface<T> extends Immutable<T> {

    public interface BuilderInterface<T> extends Immutable.Builder<T> {
    }
}


public abstract class AbstractClass<T> implements Interface<T> {

    public static class AbstractBuilder<T> implements Interface.BuilderInterface<T> {

        private final T object;

        public AbstractBuilder(T object) {

            this.object = object;
        }

        @Override
        public T build() {

            return this.object;
        }
    }

    protected AbstractClass() {

        super();
    }
}


public class ConcreteClass extends AbstractClass<ConcreteClass> {

    public ConcreteClass() {

    }

    @Override
    public Builder<ConcreteClass> builder() {
        return new AbstractClass.AbstractBuilder<ConcreteClass>(this);
    }
}