英文:
java.util.Function source code wildcard boundary usage understanding
问题
尝试理解 java.util.Function
的源代码
尝试创建了自己版本的这个类,在将我的版本与源代码进行比较后,发现一个区别 - 不理解在使用泛型类型边界的背后原因。
我的版本
default <V> MyFunction<T, V> andThen(MyFunction<? super R, V> after) {
return t -> after.apply(apply(t));
}
Java源代码
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
方法几乎相同,不同之处在于在方法中使用了 ? extends V
,而非直接使用了 V
。
为什么在 andThen
方法中使用类型上界 ? extends V
- 是否存在某种情况只能使用 ? extends V
而不能使用 V
注意:我理解 ? super R
部分是必需的,因为如果没有它,我们只能链接另一个输入参数类型完全为 R
的函数。
关于 compose
方法中使用 ? super V
的用法也存在同样的疑问。
英文:
Trying to understand the source code of java.util.Function
Have attempted to create my own version of this class, on comparing my version with source code, found one difference - unable to understand the reason behind usage of a generic type boundary.
myVersion
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));
}
this is pretty much the same as java.util.Function
andThen
method except that instead of ? extends V
, V
has been used.
why is the type upper bound ? extends V
used in andThen
method - is there any scenario that will only work with ? extends V
and not with V
note: I understand the ? super R
part is required because without it, we will only be able to chain another function that has the input argument type exactly as R
Have the same doubt about the usage of ? super V
in compose
method also
答案1
得分: 4
Function
接口和你的MyFunction
接口都应该考虑使用PECS的设计原则(链接什么是PECS(生产者扩展消费者超级)已经通过评论提供)。
虽然MyFunction
可以编译并且可以使用简单的返回类型V
,但它可以变得更加灵活。这个例子可能有点牵强,但它说明了通过将其改为? extends V
可以添加的灵活性。
MyFunction<Integer, Integer> first = x -> x + 1;
MyFunction<Integer, Integer> second = x -> x * 2;
MyFunction<Integer, Number> andThen = first.andThen(second);
除非你让返回类型包括? extends V
,否则最后一行无法编译通过。这允许声明一个函数变量返回更宽的类型。V
被推断为Number
,而? extends V
部分允许它接受返回Integer
(一个子类型)的函数。
当需要这种灵活性时会发生什么,例如当返回类型可能不是Integer
,而是Number
时呢?
MyFunction<Integer, Double> third = x -> x / 3.0;
andThen = first.andThen(third);
当您需要在同一对象层次结构内组合可能返回不同类型的函数时,例如Integer
或Double
都是Number
时,这将非常有用。如果将返回类型限制为V
,则无法实现此灵活性。变量andThen
不能用于andThen
调用的两个结果。
当然,你可以强制变量类型与andThen
的返回类型相同,但是限制用户调用你的代码的灵活性是没有理由的。
生产者扩展,为了灵活性。
英文:
The Function
interface, and your MyFunction
interface, should both be designed with PECS in mind (link What is PECS (Producer Extends Consumer Super)? already supplied by a comment).
While MyFunction
can compile and be used with a simple return type of V
, it can be made more flexible. This example may be a little contrived but it illustrates the flexibility that can be added by making it ? extends V
instead.
MyFunction<Integer, Integer> first = x -> x + 1;
MyFunction<Integer, Integer> second = x -> x * 2;
MyFunction<Integer, Number> andThen = first.andThen(second);
The last line won't compile unless you make the return type include ? extends V
. This allows a function variable to be declared to return a wider type. The V
is inferred as Number
, and the ? extends V
part allows it take functions that return Integer
, a subtype.
What happens when one needs such flexibility, e.g. when the return type may not be an Integer
, but it is a Number
?
MyFunction<Integer, Double> third = x -> x / 3.0;
andThen = first.andThen(third);
This is useful when you need to compose functions that may return a different type within the same object hierarchy, e.g. Integer
or Double
are both Number
s. This flexibility is not possible if you limit the return type to V
. The variable andThen
can't be used for both results of andThen
calls.
Sure, you could force a variable type to be the same as the return type of andThen
, but there's no reason to limit the flexibility of a user calling your code.
Producer extends, for flexibility.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论