I have a public API, used several times across several projects:
public interface Process<C extends ProcessExecutionContext> {
Future<?> performAsync(C context);
}
And an abstract class that takes care of implementing the Future mechanism (not shown). I know that all projects subclass the corresponding abstract class (for which performAsync is final) and no single class implements the abstract interface without subclassing the abstract implementor. This is by design and because this "public" API is "public" within our company.
Finding that Future
is too limitative compared to Spring's ListenableFuture
I decided to extend the interface to
public interface Process<C extends ProcessExecutionContext> {
ListenableFuture<?> performAsync(C context);
}
And I already implemented the ListenableFuture in the single abstract superclass not shown in the example. No other implementation exists, by design.
Every caller so far uses Future
which is a superinterface of ListenableFuture
. Code compiles well if you use Future<?> future = processReturningListenable.performAsync(context)
.
Question is: if I deploy an up-to-date JAR of the public API, containing both the interface and the abstract superclass with ListenableFuture
implementation to existing environments, without recompiling all the projects, does the performAsync
call still work?
I.e. does Java grant binary compatibility of interfaces when they are replaced with a method that return a subtype of the original type?
I am asking this because 1) I find no one available for doing a simple test with an existing JAR file and 2) having to recompile all projects is a red alert.
I assume what I ask is possible because Java method names are identified by a signature that counts the method name and the input parameters. Changing the output parameters doesn't change the method's name