2

I have a situation where I need to grab a reference to an enclosing anonymous inner class:

I have some asynchronous method doSomething(...) that calls a result-callback when it's done (given to me by a library; can't change this) and I'm trying to write a result-callback that automatically retries the doSomething(...) call a couple of times if it fails by posting a Runnable to a message queue that gets executed after a 100-ms retry-delay.

Since that call needs to again pass in the same result-callback, I need to get a reference to my result-callback from within the Runnable's run-method like so:

interface ResultListener {
    public void onSuccess();
    public void onFailure();
}

private static void doSomething(ResultListener listener) {
    // Do something fun here...
}

public static void main(String[] args) throws IOException {

    final ResultListener autoRetry = new ResultListener() {
        @Override
        public void onSuccess() {
            // Yay! Everything works!

        }

        @Override
        public void onFailure() {

            final ResultListener outerThis = this;  // This can't be necessary!

            // Schedule retry in 100ms
            messageThread.postDelayed(new Runnable() {
                @Override
                public void run() {
                    doSomething(outerThis);  // What else could I do here?
                }
            }, 100);
        }
    };

    doSomething(autoRetry);

}

Is using this outerThis-hack the only way to do this? It seems really clunky. The following don't work:

  • this - returns the instance of Runnable, not the anonymous ResultListener
  • ResultListener.this (which I would have expected to work) throws No enclosing instance of the type ResultListener is accessible in scope
  • autoRetry throws The local variable autoRetry may not have been initialized

Clearly, I could just name the anonymous class by defining a RetryListener class, which I then instantiate instead and use RetryListener.this, but this again seems like it shouldn't be necessary...

Am I missing something?

Markus A.
  • 12,349
  • 8
  • 52
  • 116
  • Because you have an anonymous class within an anonymous class, I don't think it's possible to refer to the outer from the inner because it isn't named, like you said. Good question, though! – Jacob G. Jul 20 '18 at 19:12
  • 4
    From a code quality perspective, I would rather ask myself how to avoid that "double stuffing" here. The question is not how to pass "this" more elegantly, but how to well, avoid double stuffing of anonymous inner classes! – GhostCat Jul 20 '18 at 19:14
  • @GhostCat Other than changing the anonymous inner class to a named class that's declared somewhere else (which moves the code away from where it's used), do you have any ideas on how to best do this? :) In this case, the anonymous classes seem like the cleanest way to do this, but maybe I'm missing something? – Markus A. Jul 20 '18 at 20:05
  • You should be able to use `autoRetry` inside of your run method. It's declared final, which means you can access it within your anonymous class. – Martin Cassidy Jul 20 '18 at 21:09
  • @MartinCassidy unfortunately, that gives me an error, as described above. It evaluates the class declaration before it assigns it to the variable. – Markus A. Jul 20 '18 at 22:03

0 Answers0