【问题标题】:Why Reactor Mono<Void> is recognized as an empty Mono?为什么 Reactor Mono<Void> 被识别为空的 Mono?
【发布时间】:2020-03-30 11:11:51
【问题描述】:

这是一段代码

@Test
public void test_mono_void_mono_empty() {
    Mono.just("DATA")
        .flatMap(s -> Mono.just(s.concat("-")
                                 .concat(s))
                          .doOnNext(System.out::println)
                          .then())
        .switchIfEmpty(Mono.just("EMPTY")
                           .doOnNext(System.out::println)
                           .then())
        .block();
}

向控制台提供以下结果:

DATA-DATA
EMPTY

这意味着第一个flatMap 中的链被识别为空链。

另一方面,Reactor 具有以下类 MonoEmpty,它由 Mono.empty() method 返回。最重要的是,该方法说明了以下内容:

/**
 * Create a {@link Mono} that completes without emitting any item.
 *
 * <p>
 * <img class="marble" src="doc-files/marbles/empty.svg" alt="">
 * <p>
 * @param <T> the reified {@link Subscriber} type
 *
 * @return a completed {@link Mono}
 */
public static <T> Mono<T> empty() {
    return MonoEmpty.instance();
}

没有发出任何项目 - 但我使用 then() 方法发出了 Void 类型的对象。

对此有何解释?

【问题讨论】:

  • s.concat("-").concat(s) 应该写成s + "-" + s
  • @LinosaysReinstateMonica 没有发现任何区别
  • + 可以由编译器优化,而使用 concat() 你没有这样的保证:stackoverflow.com/a/47626/5515060
  • 我的意思是问题的范围没有区别。它与主题有什么关系?
  • 不是,但必须是吗?我只是提出了一个改进

标签: java project-reactor reactor


【解决方案1】:

好的,答案在official java doc 中,上面写着The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void。

这意味着它的主要思想只是将 void 返回类型表示为一个类并包含一个Class&lt;Void&gt; public 值。而已。此外,它不是可实例化的,因为构造函数是私有的。所有这些随后意味着我们可以分配给Void 变量的唯一值是null,它始终被识别为empty Mono。

有用的讨论: Java generics void/Void types

【讨论】:

  • "我们可以分配给 Void 变量的唯一值是 null,它始终被认为是空 Mono" - 请注意这一点;它可能会巧妙地忽略这里发生的事情。您根本无法通过响应式流传播 null,但您可以在完成信号之前根本不传播任何内容(Mono&lt;Void&gt; 暗示。)
【解决方案2】:

给定的Mono 可以在发送完成信号之前发布任何内容或单个值。 (它不能发布null - 反应规范禁止它。)Mono 的泛型类型表示可能被发射的对象的类型 - 但不能保证它将发射。

例如,Mono&lt;Foo&gt; 可以只发出一个完成信号,或者一个 Foo 的实例然后发出一个完成信号。

有两种常见情况可能无法发布值 - 第一种是值可能存在也可能不存在(例如在数据库或集合中搜索项目)。在这种情况下,您仍然会使用Mono&lt;SomeType&gt;,它可能会或可能不会发出SomeType 实例。第二种情况是如果一个值肯定会永远被发布(通常在您只需要通知任务已完成时使用),为此,按照惯例,总是使用Mono&lt;Void&gt;。 then(),在你上面的例子中,属于第二种情况。

Mono&lt;Void&gt; 是一个特殊情况的原因是,正如您所指出的,Void 是一个永远无法通过设计实例化的类。因此不存在Void 的实例,这意味着Mono 永远不能在其完成信号之前发出值。

因此,合乎逻辑的结论是,Mono&lt;Void&gt; 类型的发布者永远不能发出值,只能发出完成信号 - 所以它就是这样使用的。

【讨论】:

    猜你喜欢
    • 2018-06-18
    • 1970-01-01
    • 2022-10-24
    • 1970-01-01
    • 1970-01-01
    • 2020-03-17
    • 2021-11-23
    • 2021-06-12
    • 2018-12-26
    相关资源
    最近更新 更多