Spliterator.OfInt 中 tryAdvance 的奇怪实现
Weird implementation of tryAdvance in Spliterator.OfInt
它是如何工作的?
Consumer<? super Integer>
如何转换为IntConsumer
??
default boolean tryAdvance(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
return tryAdvance((IntConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)");
return tryAdvance((IntConsumer) action::accept);
}
}
强制转换为绑定方法引用 action::accept
提供 目标类型 ,它等同于 lambda x -> action.accept(x)
。 IntConsumer
目标类型导致此 lambda(更愿意接受整数)适应接受 int(这将导致参数在传递给 action.accept()
之前被隐式装箱)。
您的问题不是很清楚,因为发布的代码中有 两个 类型转换。
第一个通过 instanceof
检查 Consumer<? super Integer>
是否也实现了 IntConsumer
然后进行普通类型转换,假设 class 实现 Consumer
和 IntConsumer
同时使用相同的语义。与 the documentation 比较:
Implementation Requirements:
If the action is an instance of IntConsumer
then it is cast to IntConsumer
and passed to tryAdvance(java.util.function.IntConsumer);
otherwise the action is adapted to an instance of IntConsumer
, by boxing the argument of IntConsumer
, and then passed to tryAdvance(java.util.function.IntConsumer)
.
所以第一个 instanceof
检查和类型转换是契约的第一部分,如果 action
参数实现了两个接口,则避免装箱。
第二种类型转换是描述的对拳击 IntConsumer
改编的一部分,而拳击是由 method reference (IntConsumer) action::accept
. This method reference refers to the method void accept(T t)
(where T := ? super Integer
) which can be adapted to the function signature of IntConsumer
, as 暗示的。由于此功能签名不仅满足 IntConsumer
的签名,而且(当然)Consumer<? super Integer>
的签名需要类型转换来消除重载的 tryAdvance
方法之间的歧义。当使用等价的 lambda 表达式
时就没有必要了
return tryAdvance((int i)->c.accept(i));
它是如何工作的?
Consumer<? super Integer>
如何转换为IntConsumer
??
default boolean tryAdvance(Consumer<? super Integer> action) {
if (action instanceof IntConsumer) {
return tryAdvance((IntConsumer) action);
}
else {
if (Tripwire.ENABLED)
Tripwire.trip(getClass(),
"{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)");
return tryAdvance((IntConsumer) action::accept);
}
}
强制转换为绑定方法引用 action::accept
提供 目标类型 ,它等同于 lambda x -> action.accept(x)
。 IntConsumer
目标类型导致此 lambda(更愿意接受整数)适应接受 int(这将导致参数在传递给 action.accept()
之前被隐式装箱)。
您的问题不是很清楚,因为发布的代码中有 两个 类型转换。
第一个通过 instanceof
检查 Consumer<? super Integer>
是否也实现了 IntConsumer
然后进行普通类型转换,假设 class 实现 Consumer
和 IntConsumer
同时使用相同的语义。与 the documentation 比较:
Implementation Requirements:
If the action is an instance of
IntConsumer
then it is cast toIntConsumer
and passed totryAdvance(java.util.function.IntConsumer);
otherwise the action is adapted to an instance ofIntConsumer
, by boxing the argument ofIntConsumer
, and then passed totryAdvance(java.util.function.IntConsumer)
.
所以第一个 instanceof
检查和类型转换是契约的第一部分,如果 action
参数实现了两个接口,则避免装箱。
第二种类型转换是描述的对拳击 IntConsumer
改编的一部分,而拳击是由 method reference (IntConsumer) action::accept
. This method reference refers to the method void accept(T t)
(where T := ? super Integer
) which can be adapted to the function signature of IntConsumer
, as IntConsumer
的签名,而且(当然)Consumer<? super Integer>
的签名需要类型转换来消除重载的 tryAdvance
方法之间的歧义。当使用等价的 lambda 表达式
return tryAdvance((int i)->c.accept(i));