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 不同类型的函数时,这很有用,例如Integer
或 Double
都是 Number
。如果将 return 类型限制为 V
,则无法实现这种灵活性。变量 andThen
不能用于 andThen
调用的两个结果。
当然,您可以强制变量类型与 andThen
的 return 类型相同,但没有理由限制用户调用您的代码的灵活性。
生产者为了灵活性而扩展。
试图理解 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 不同类型的函数时,这很有用,例如Integer
或 Double
都是 Number
。如果将 return 类型限制为 V
,则无法实现这种灵活性。变量 andThen
不能用于 andThen
调用的两个结果。
当然,您可以强制变量类型与 andThen
的 return 类型相同,但没有理由限制用户调用您的代码的灵活性。
生产者为了灵活性而扩展。