Cla*_*oft 6 java scala type-variables bounded-wildcard
以下签名在Scala中有效且常用:
trait Collection[A] {
def reduceLeft [B >: A] (f: (B, A) => B): B
}
Run Code Online (Sandbox Code Playgroud)
但是,由于Java中>:的Scala是等效的super,我转换此签名的第一个想法(用函数类型替换BiFunction并使用Use-Site variance annotations aka Bounded Wildcards)将是
interface Collection<A> {
<B super A> B reduceLeft(BiFunction<? super B, ? super A, ? extends B> mapper)
}
Run Code Online (Sandbox Code Playgroud)
但是哦,不!编译器抱怨super令牌,<B super A>因为你不能有低边界的类型变量!现在,如何在Java代码中编写此方法而不必回顾Java世界中不存在泛型的时间?
是的,我知道你认为我可以使用B extends A,但这不是一回事,正如我的实现所示:
public <R extends E> R reduceLeft(BiFunction<? super R, ? super E, ? extends R> mapper)
{
if (this.isEmpty())
{
return null;
}
Iterator<E> iterator = this.iterator();
R first = iterator.next(); // doesn't work, but would if R was a super-type of E (R super E)
while (iterator.hasNext())
{
mapper.apply(first, iterator.next());
}
return first;
}
Run Code Online (Sandbox Code Playgroud)
相反,我不得不使用这个稍微受限制的版本:
public E reduceLeft(BiFunction<? super E, ? super E, ? extends E> mapper)
{
if (this.isEmpty())
{
return null;
}
Iterator<E> iterator = this.iterator();
E first = iterator.next();
while (iterator.hasNext())
{
first = mapper.apply(first, iterator.next());
}
return first;
}
Run Code Online (Sandbox Code Playgroud)
B >: AScala 方法定义中的约束是必要的,因为:
reduceLeft从概念上讲,需要返回 type 的值A,但用作A返回类型意味着在协变位置使用它,这与已经声明的方差冲突,即A必须是协变的。解决这种差异冲突的技巧是引入B泛型类型。
现在,正如您所提到的,Java 采用了使用站点差异,因此用 Java 编写的任何集合都将是不变的。A这也意味着用作方法的返回类型(即逆变位置)没有问题。因此,下面的定义应该足够 \xe2\x80\x94 ,不需要类型B:
interface Collection<A> {\n A reduceLeft(BiFunction<? super A, ? super A, ? extends A> reducer);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n然而,正如您所看到的,A一次为下限,然后为上限的最终效果是A基本上是不变的 \xe2\x80\x94 如果不使用向下转换,就不可能从通配符边界中受益。这意味着我们可以简化签名(与 非常相似Stream.reduce):
interface Collection<A> {\n A reduceLeft(BiFunction<A, A, A> reducer);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n此外,类型BiFunction<A, A, A>, 已经以名称 出现在 Java 8 中BinaryOperator<A>。
| 归档时间: |
|
| 查看次数: |
256 次 |
| 最近记录: |