gpt4 book ai didi

java - 为什么Java函数式接口(interface)作为参数通常使用逆变arg类型?

转载 作者:行者123 更新时间:2023-11-29 03:12:12 24 4
gpt4 key购买 nike

java.util.function.Consumer为例:

它有一个方法

andThen(Consumer<? super T> after)

java.util.function 中的大多数(全部?)方法将功能接口(interface)作为参数使用通配符和 super。这有什么好处?

最佳答案

这与它们是函数式接口(interface)关系不大,而与如何在方法中使用参数关系更大。

通配符参数化类型(无界、上限或下限)允许参数化类型的多态性。这是必要的 Foo<S>不是 Foo<T> 的子类型即使ST 的子类型.然而,声明为 Foo<? extends T> 的参数可以同时接受 Foo<S>Foo<T>其中 S extends T .同样Foo<? super S>可以同时接受 Foo<S>Foo<T>其中 S extends T , 但不同于 extends形式它不能接受参数化类型,其中类型参数是 S 的子类型.

A lower bounded wildcard parameterized type因此允许声明参数的方法将项(在本例中为 T 类型)作为参数传递给参数上的方法(在本例中为接口(interface))。这在 andThen 的情况下是有意义的因为该参数是一个“out”参数:它存储数据以供稍后在方法外部使用(在调用站点,或者在调用站点通过object to) 它允许您将数据传递给它(并且可能将该数据从方法“输出”回调用站点)。

Consumer 的情况下接口(interface)这是有道理的。该接口(interface)表示一个类 acceptT 类型的项目.它可以与任何其他 Consumer 链接, 那可能是 Consumer<P>其中 T extends P ;这意味着第二个消费者可以更通用,但仍然可以传递第一个消费者接受的相同项目。

这对于 upper bounded wildcard 是不可能的参数,因为这些是“in”参数:它们向传递给它们的方法提供数据。 (如果参数 unbounded 简单地声明为 Foo<?> 那么它隐含上界,由 Object 决定,所以实际上与上界通配符参数化类型没有什么不同)。 p>

例子:

abstract class Animal {}
class Cat extends Animal {}
class Dog extends Animal {}
class Labrador extends Dog {}

andThen(Consumer<? super Dog> after) :

  • 可以接受Consumer<Dog> , Consumer<Animal>Consumer<Object>
  • 在我们知道我们可以做的方法里面accept(new Dog())无论 Consumer 的类型如何传入的是:它将始终代表 Consumer Dog 的父类(super class)型因此 accept一个Dog

现在我们可以做:

Consumer<Dog> takeToDogKennel = new Consumer<Dog>(); // only for dogs
Consumer<Animal> giveWater = new Consumer<Animal>(); // dogs and cats too
takeToDogKennel
.andThen(giveWater)
.accept(new Labrador());

The Java Tutorials, Guidelines for Wildcard Use更详细地解释输入/输出参数。

实际上 andThen是带有“out”参数的方法的一个坏例子 - 它混淆了问题,因为它只是“通过副作用操作”(根据文档)。

关于java - 为什么Java函数式接口(interface)作为参数通常使用逆变arg类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28755488/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com