I've started working on an existing project (an sdk) at work, and the code base uses listeners like there's no tomorrow. Pretty much every second method takes some sort of listener argument and I have yet to find an occurrence where the listener is not the calling class or an anonymous class declared when the method is called.My question is: when/why is it appropriate to use a Listener over Future<> in this way?// Util methodsstatic void postSuccess(Listener listener, Object object) {    Util.runOnUI(() -> { listener.success(object); });}static void postError(Listener, Exception ex) {    Util.runOnUI(() -> { listener.failure(ex); });}void foo ( Bar bar, Listener listener ) {    executor.submit(() -> {        try {            // work_on() is a potentially long running function            Result res = work_on( bar );            Util.postSuccess(listener, res)         }         catch (Exception ex) {            Util.postError(listener, ex);         }     }}In the above code the caller has no control over when the listener's method is invoked. The following code would allow the caller to decide whether to wait or check it later and generally seems to provide more control:Future<Result> foo ( Bar bar ) {    return executor.submit(() -> { return workOn( bar ) };}Apologies if I'm missing something obvious, I'm only out of college three months, but this listener code smells bad to me.
When to use Future<> vs Listener
java;concurrency;callbacks
With both alternatives, you can achieve the same functionality: running some long piece of code without blocking the caller and provide a mean to give the result later.But from my own experience, I always foster Future over callback for the following reasons:Program flow is much harder to understand with callbacks than with Future. The flow is like jumping making it also hard to debug.Callbacks denature the method's signature. When you look at void foo(Bar bar, Listener listener), first: it returns void although we would have expected this method to return something in a synchronous context. Second: the parameters list is polluted with a Listener that has nothing to do with the domain (= visual noise). On the other hand, with a Future the intent is clearer: I need a Bar in order to deliver you a Result, but not directly, only in some future.You can end up in the callback hell. With Future your code stays more composable and evolutive. By the way, Java 8 is also shipped with a whole new API called CompletableFuture that makes the usage of asynchronism more expressive and relies on Future.With callbacks, you enforce the thread in which the listener is called (in your case the UI thread). But what if the user doesn't want the callback to be run in the UI thread ? It's too late because this dependency has been hardcoded in your code and the caller is stuck. With Future the caller is free to choose the thread he wants to handle the result in.Callbacks can create a lot of garbage threads if done carelessly because each listener has to be invoked in another thread (this is, however, not the case in your example since you always use the UI thread). With Future only one thread is involved.