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?
Advertisement
Answer
This is the way how java generics works. In the second example java compiler could infer type. This is the same as defining
Mono<InterfaceA> getMonoA() { return Mono.<InterfaceA>just(new ClassA()); }
But in the first example compiler could not cast Mono<ClassA>
to Mono<InterfaceA>
automatically but you could cast it by apply a map function
Mono<InterfaceA> getMonoA() { return ClassA.getMonoA1().map(Function.identity()); }
that is the same as defining .<InterfaceA>map(c -> c)
or .map(c -> (InterfaceA) c)
.
or you could define your method as
public static <T extends InterfaceA> Mono<T> getMonoA() { return ClassA.getMonoA(); }
similar how Mono.just
is defined.
Due to type erasure, both Mono<InterfaceA>
and Mono<ClassA>
will be Mono
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 in ClassCastException
when you try to access the object
Mono<InterfaceA> getMonoA() { return (Mono) ClassA.getMonoA(); }
It’s not something specific to Reactor or WebFlux. The same is valid for any generic types. For example, List<InterfaceA>
vs List<ClassA>
.