使用泛型时,构造函数和构建器之间有什么区别?

What is the difference between a constructor and a builder when using generics?

在Java中编程时遇到了以下问题。

当使用构造函数时:以下代码工作正常。

public class Generics<T> {

    private T data;

    public static <T> Generics<T> of(T data) {
        return new Generics<>(data);
    }

    public Generics(T data) {
        this.data = data;
    }
}

使用builder时:报错如下提供Object类型

我使用了 Project Lombok 提供的构建器。

为什么上面代码中的生成器泛型不起作用?

显然 Lombok 生成了一个静态泛型 builder() 方法。您可以在方法名称前使用 <T> 指定泛型静态方法的泛型类型,如:

return Generics.<T>builder()
          .data(data)
          .build();

如果您在调用 builder() 时未指定泛型类型,您将获得原始类型,此时泛型类型推断将不再起作用。

您需要显式添加泛型:return Generics.<T>builder() - 添加 <T> 一切都会好起来的。

说明

Java 是强类型的:每个表达式以及表达式的几乎每个部分都有一个实际类型; java 不允许事后搁置;没有所谓的“中间件 - 嗯,我们会看到它的去向”。

Generics.builder(),作为一个表达式,需要系统打字。构建器 class 需要 <T> 一样(它是 Generics.GenericsBuilder<X> - 其中 Builder 是泛型的静态内部 class,定义为 public static class GenericsBuilder<X>.

Java 不能直接得出您希望 X 和 T 为同一类型的结论。

展望未来,它可以计算出 X 应该是 T 'automatically',而无需您的参与:它可以检查 .data(data) 调用,前提是定义了 data 方法在生成器中为:

public GenericsBuilder<X> data(X data)

因此,无论什么类型 data(变量)might be (it'sThere, given that it's the parameter defined asT 数据`),因此,java 可以得出 X 应该是 T 的结论.

否则,java 可以看得更远,到 build(),并注意这个 returns X,并且正在 returned通过一个 return 类型被定义为 T 的方法,因此也给 java 机会说:啊,X == T,对。

但这不是 java 的工作方式。在很大程度上是因为当您刚刚创建的构建器的 X(声明 public static <X> Generics.GenericsBuilder<X> builder() 中的 X 时,即使弄清楚 .data 方法可能意味着什么也很难做到) 必须在某种未知的边缘状态中保留一段时间,因为解析器会继续尝试弄清楚其余部分的含义。鉴于 java 允许方法重载(2 个不同的方法具有相同的名称和相同数量的参数,但不同的参数类型,可能包含泛型来引导) - 这将是一个组合爆炸,意味着你可以写java 需要数年才能解析的代码。

因此,java 不能那样工作,它必须从表达式 Generics.builder() 中单独 确定 X 应该是什么 ,显然不能。

解决方案是使用这种有点奇特的语法明确地编写它:Generics.<T>builder().