Reactor/WebFlux 的类型推断和类型变异问题
假设有一个接口及其实现类:
public interface InterfaceA {}
public class ClassA implements InterfaceA {
public static Mono<ClassA> getMonoA() {
return Mono.empty();
}
}
然后,对于方法 Mono
,以下实现会导致编译错误:
Mono<InterfaceA> getMonoA() {
return ClassA.getMonoA();
}
不变类型 Mono
不是 Mono
的超类是有道理的> 即使 InterfaceA
是 ClassA
的超类,因此 ClassA.getMonoA()
的返回类型是Mono
与 Mono
不匹配。
但是,以下实现可以正常工作:
Mono<InterfaceA> getMonoA() {
return Mono.just(new ClassA());
}
Mono.just
方法实际上定义为 public static
。由于我的例子中的通用类型 T
是 ClassA
,该方法应该返回 Mono
的类型,这也应该引发编译错误在我心里。
我想知道是否有一些机制让 Mono.just
方法返回 Mono
而不是 Mono
?
Let's say there is an interface and its implement class as:
public interface InterfaceA {}
public class ClassA implements InterfaceA {
public static Mono<ClassA> getMonoA() {
return Mono.empty();
}
}
And then, for the method Mono<InterfaceA> getMonoA()
, the following implementation causes a compile error:
Mono<InterfaceA> getMonoA() {
return ClassA.getMonoA();
}
It makes sense that the invariance type Mono<InterfaceA>
is not the super class of Mono<ClassA>
even if InterfaceA
is the super class of ClassA
and therefore the return type of ClassA.getMonoA()
which is Mono<ClassA>
does not match the Mono<InterfaceA>
.
However, the following implementation works properly:
Mono<InterfaceA> getMonoA() {
return Mono.just(new ClassA());
}
The Mono.just
method is acturally defined as public static <T> Mono<T> just(T data)
. As the geneic type T
in my case is ClassA
, the method should return the type of Mono<ClassA>
which should also raise a compile error in my mind.
May I know if there are some mechanisms let Mono.just
method returns Mono<InterfaceA>
instead of Mono<ClassA>
please?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这就是java泛型的工作方式。在第二个示例中,java 编译器可以推断类型。这与定义相同
但在第一个示例中编译器无法自动将
Mono
转换为Mono
但您可以通过应用映射函数来转换它与定义
.map(c -> c)
或.map(c -> (InterfaceA) c)
相同。或者您可以将您的方法定义为
类似于
Mono.just
的定义方式。由于类型擦除,
Mono;
和Mono
在运行时将是Mono
,因此不会对元素类型进行真正的类型检查。您可以使用在这种情况下有效的不安全强制转换,但当您尝试访问该对象时可能会导致 ClassCastException这不是 Reactor 或 WebFlux 特有的东西。这对于任何泛型类型都有效。例如,
List
与List
。This is the way how java generics works. In the second example java compiler could infer type. This is the same as defining
But in the first example compiler could not cast
Mono<ClassA>
toMono<InterfaceA>
automatically but you could cast it by apply a map functionthat is the same as defining
.<InterfaceA>map(c -> c)
or.map(c -> (InterfaceA) c)
.or you could define your method as
similar how
Mono.just
is defined.Due to type erasure, both
Mono<InterfaceA>
andMono<ClassA>
will beMono
during runtime, so there will be no real type check regarding the element type. You could use unsafe cast that will work in this case but potentially could result inClassCastException
when you try to access the objectIt's not something specific to Reactor or WebFlux. The same is valid for any generic types. For example,
List<InterfaceA>
vsList<ClassA>
.我认为看待这个问题的一种方法是编译器如何解释类型
T
。如果您定义,则以下内容将不会编译(如预期),
并显示类似于此的消息
因此编译器会检查类型
T
是否对应于方法的返回类型。MonoJust
是 已定义作为通用发布者,您返回的是MonoJust
而不是MonoJust
。另一方面,
MonoEmpty
是定义为Publisher
并且您必须定义类型边界:
I think one way to look at this is the question how the type
T
is interpreted by the compiler. If you definethen the following will not compile (as expected)
with the message similar to this one
So the compiler does check if the type
T
corresponds to the return type of the method.MonoJust
is defined as a generic Publisher and you are returningMonoJust<InterfaceA>
notMonoJust<ClassA>
.On the other hand,
MonoEmpty
is defined as aPublisher<Object>
:and you would have to define type boundaries: