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

huangapple go评论62阅读模式
英文:

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.FunctionandThen 方法几乎相同,不同之处在于在方法中使用了 ? 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);

当您需要在同一对象层次结构内组合可能返回不同类型的函数时,例如IntegerDouble都是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&lt;Integer, Integer&gt; first = x -&gt; x + 1;
MyFunction&lt;Integer, Integer&gt; second = x -&gt; x * 2;
MyFunction&lt;Integer, Number&gt; 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&lt;Integer, Double&gt; third = x -&gt; 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 Numbers. 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.

huangapple
  • 本文由 发表于 2020年10月22日 01:28:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/64468731.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定