java.util.Function 源码通配符边界使用理解

java.util.Function source code wildcard boundary usage understanding

试图理解 java.util.Function

的源代码

曾尝试创建我自己的版本 class,在将我的版本与源代码进行比较时,发现了一个差异 - 无法理解使用泛型类型边界背后的原因。

我的版本

default <V> MyFunction<T, V> andThen(MyFunction<? super R, V> after) {
        return t -> after.apply(apply(t));
}

javaSource

default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}

这与 java.util.Function andThen 方法几乎相同,只是使用的是 V 而不是 ? extends V

为什么在 andThen 方法中使用类型上限 ? extends V - 是否有任何场景只适用于 ? extends V 而不适用于 V

注意:我知道 ? super R 部分是必需的,因为没有它,我们将只能链接另一个输入参数类型与 R

完全相同的函数

compose方法中? super V的用法也有同样的疑问

Function 界面和您的 MyFunction 界面在设计时都应考虑到 PECS(link What is PECS (Producer Extends Consumer Super)? 已由评论提供)。

虽然 MyFunction 可以编译并与 V 的简单 return 类型一起使用,但它可以变得更加灵活。这个例子可能有点做作,但它说明了可以通过将其设为 ? extends V 而增加的灵活性。

MyFunction<Integer, Integer> first = x -> x + 1;
MyFunction<Integer, Integer> second = x -> x * 2;
MyFunction<Integer, Number> andThen = first.andThen(second);

除非您使 return 类型包含 ? extends V,否则最后一行不会编译。这允许将函数变量声明为 return 更广泛的类型。 V 被推断为 Number? extends V 部分允许它采用 return Integer 的子类型的函数。

当需要这种灵活性时会发生什么,例如当 return 类型可能不是 Integer,而是 Number?

MyFunction<Integer, Double> third = x -> x / 3.0;
andThen = first.andThen(third);

当您需要在同一对象层次结构中编写可能 return 不同类型的函数时,这很有用,例如IntegerDouble 都是 Number。如果将 return 类型限制为 V,则无法实现这种灵活性。变量 andThen 不能用于 andThen 调用的两个结果。

当然,您可以强制变量类型与 andThen 的 return 类型相同,但没有理由限制用户调用您的代码的灵活性。

生产者为了灵活性而扩展。