【问题标题】:Java Consumer InterfaceJava 消费者接口
【发布时间】:2019-08-02 11:58:47
【问题描述】:

有人可以帮助我理解 Java 8 功能接口中的以下代码 根据我的理解,accept() 将其作为输入并对其进行处理,但在 andThen() 的情况下不返回任何值,它是如何工作的

accept() 方法将类型 T 作为输入并且不返回任何值。

default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
}

【问题讨论】:

  • (T t) -&gt; { accept(t); after.accept(t); } 又是一个Consumer,它确保当前消费者首先是accepted,然后提到的afteraccepted。
  • 但是accept方法没有返回任何值那么我们怎么会得到Consumer呢?
  • @NPE 返回的值是完整的:(T t) -&gt; { accept(t); after.accept(t); },而不是调用 accept(t) 的结果。

标签: java java-8 functional-programming


【解决方案1】:

一个函数式接口必须只有一个抽象方法。但是,它可以拥有任意数量的静态和默认方法。 Consumer的方法有:

  1. accept(T)

    • 这是Consumer 的单一抽象方法。它接受T 类型的单个通用参数并且不返回任何内容(即void)。这是由 lambda 表达式或方法引用实现的方法。
  2. andThen(Consumer)

    • 这是一种默认方法。换句话说,它有一个实现,因此是非抽象的。该方法接受Consumer 并返回另一个Consumer。由于是默认方法,Consumer 的单一抽象方法仍然是accept(T)

上面解释了为什么Consumer 可以有一个返回void 以外的东西的方法。现在,当谈到andThen 的实现时,重要的是要意识到实际上涉及三个 Consumers:

  1. 调用andThen 的实例。
  2. after引用的实例。
  3. 实例返回给调用者。

如果您对代码进行格式化,以便并非所有内容都在同一行,则可能更容易理解:

default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    // Returns Consumer instance #3. The lambda is the implementation
    // of the 'accept' method.
    return (T t) -> {
        accept(t);       // Invokes 'accept' on Consumer instance #1.
        after.accept(t); // Invokes 'accept' on Consumer instance #2.
    }
}

【讨论】:

    【解决方案2】:

    为了了解从该 API 获得 returned 的内容,您可以尝试将实现可视化为:

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return new Consumer<T>() { // return the complete Consumer implementation
            @Override
            public void accept(T t) {
                Consumer.this.accept(t); // accept current consumer
                after.accept(t); // and then accept the 'after' one.
            }
        };
    }
    

    现在把它联系起来

    (T t) -> { accept(t); after.accept(t); } 
    

    返回的是Consumer,它确保当前是accepted,然后是after

    【讨论】:

    • @Naman 为什么我们必须做 Consumer.this.accept(t)?我没有得到这个。
    • @IfOnly 这是一个"qualified this",因此调用了 enclosure 实例的accept 方法。如果没有限定条件,则将调用当前实例 (this) 的 accept 方法,从而导致无限递归。在这种情况下有点令人困惑,因为我们有一个匿名的 Consumer 被另一个 Consumer 包围,但这与 this Q&A 中给出的示例没有什么不同。
    【解决方案3】:

    我想我理解你的担心。你想知道如果 accept() 返回 void,为什么你可以在 accept() 之后调用 andThen()

    问题是,您首先定义一个Consumer 对象,然后在该实例上调用andThen() 方法。例如:

    Consumer<String> consumer = s -> System.out.println(s);
    consumer.andThen(s -> System.out.println(s.toUpperCase()));        
    

    【讨论】:

      猜你喜欢
      • 2016-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      相关资源
      最近更新 更多