首页 > 解决方案 > 为什么builder会丢失类型?

问题描述

当我尝试这样的事情时

public class Example<T> {
    private T value;

    private Example() {

    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public static <T> Builder<T> builder() {
        return new Builder<>();
    }

    public static class Builder<T> {
        public Example<T> build() {
            return new Example<>();
        }
    }

    public static void main(String[] args) {
        Example<String> example = Example.builder().build();
        example.setValue("test");
        System.out.println(example.getValue().toUpperCase());
    }
}

我收到一个错误

Example.java:27: error: incompatible types: Example<Object> cannot be converted to Example<String>
        Example<String> example = Example.builder().build();

但是当我将类型添加到builder方法的参数时,一切正常

public static <T> Builder<T> builder(T type) {
    return new Builder<>();
}

为什么?以及如何摆脱这种虚拟类型参数?

奖励问题:如何将复杂类型传递给这样的方法?

public static <T> Builder<T> builder(Class<T> type) {
    return new Builder<>();
}

Example<Optional<String>> example = Example.builder(???).build();

更新:这只是一个例子。现实生活中的应用程序将有几个构建器在构建过程的不同阶段相互创建,当然,它们将具有接受泛型类型的方法。我希望有一种方法可以帮助编译器推断类型。我什至同意反射技巧,如果有的话,它们可以帮助我获得漂亮的 DSL。

标签: javagenerics

解决方案


Example是一个原始类,所以隐含T的是Object. 您可以在调用方法时指定泛型类型,方法是在方法调用之前将其放在尖括号 ( <>) 中:

Example<String> example = Example.<String>builder().build();
// Here --------------------------^

推荐阅读