如何创建一个真正发出元素的 Mono<Void> ?

cae*_*eus 6 void project-reactor

所以我想创建一个Mono<Void>(或任何Mono<SomeIgnorableType>)实际发出元素的。为什么?因为我实际上想运行一个效果,而结果只是意味着该效果已运行,但是,它可以被忽略。

在 Haskell 中,Void 是一种不适宜居住的类型……就像NothingScala 中的一样。在 Java 中,Void 也是不适宜居住的,但它的使用方式更像是UnitScala 中的类型或()Haskell 中的 (0 arity tuple)。一种只有一个居民的类型。

好吧,理论太多了。到目前为止我的选择:

  1. Mono.just((Void) null)抛出异常。

  2. Mono.empty().single()(因为我实际上想发出一个事件),当有人订阅它时,最终会失败。和...

  3. Mono.just("something").then()运行效果,但我无法将它与其他单声道链接,因为它只发出完整和错误事件。

又怎样???

Mic*_*rry 3

Java 缺乏空安全性意味着单元类型概念不能很好地解释。Void当人们假设等同于单位类型时,我从未被说服。你永远无法通过设计来实例化它;您可以假设任何包含该Void类型的引用是null,我并不真正将其视为一个值 - 它更多的是缺少任何值(即不可居住的类型。)

我认为 Java 中没有内置任何“真正的”单元类型,但您可以通过使用enum具有单个值的 an 来轻松创建一个单元类型:

public enum Unit {UNIT}
Run Code Online (Sandbox Code Playgroud)

如果您的Mono类型设置为Unit,这将满足您的需要 - 您可以Mono不带任何值来完成它,您可以使用单个Unit值来完成它(并忽略该值,只是对其存在的事实做出反应),或者使用一个错误。听起来这正是您所追求的。

也就是说,直接回答问题并忽略您是否应该(恕我直言,您不应该),您可以模拟Void实际为其分配一个非空值。Mockito 可以毫无问题地做到这一点,您只需要确保Mockito 已配置,以便它可以模拟最终类

Void v = Mockito.mock(Void.class);
Mono.just(v)
        .doOnNext(actualVoid -> System.out.println(actualVoid))
        .block();
Run Code Online (Sandbox Code Playgroud)

印刷:Mock for Void, hashCode: 1830745997

(这不是我曾经做过的事情,也不觉得有必要这样做,但这并不妨碍您在技术上做到这一点。)