17370845950

为什么Stream.builder()方法无法自动推断泛型类型?

Stream.builder() 泛型类型推断问题详解

Stream.builder() 方法的泛型参数在直接调用时,编译器无法自动推断。这是因为调用构造方法时缺少显式类型参数,编译器默认将其设置为 Object,导致最终结果为 Stream

代码示例:

// 默认类型参数,编译通过
Stream build = Stream.builder().add(1).build();

// 编译器报错,类型参数未知
Stream build2 = Stream.builder().add(1).build();

// 指定泛型类型,编译通过
Stream build3 = Stream.builder().add(1).build();

根本原因:

理解编译器泛型推断的关键在于泛型构造方法的调用方式。构造方法左侧的泛型参数定义了输入参数的类型,右侧定义了类内部泛型的类型。

Stream.builder() 方法的源码类似于:

public static  Builder builder() {
    return new Streams.StreamBuilderImpl();
}

调用 Stream.builder() 时, 指定了内部泛型 T 的类型为 Integer。由于没有提供输入参数,T 默认被设置为 Object

更广泛的问题:

此问题并非 Stream.builder() 独有。任何泛型类的泛型构造方法都可能遇到类似情况。

例如:

public class MyTest {
    T data;
    R member;

    public  MyTest(T data, U param, R member) {}

    public static  MyTest getBuilder() {
        return new MyTest<>();
    }

    public static void main(String[] args) {
        // 指定输入参数泛型,类泛型可省略
        MyTest myTest = new MyTest<>(233, true, "123");

        // 未指定输入参数泛型,类泛型需要显式指定
        MyTest myTest1 = MyTest.getBuilder();
    }
}

调用 MyTest getBuilder() 时, 指定了内部泛型类型,但如果 new MyTest() 不指定参数类型,编译器将报错。

解决方案:

为避免此问题,调用泛型构造方法时务必明确指定泛型参数,以便编译器正确推断。