Setting outer variable from anonymous inner class

Java doesn't know that doWork is going to be synchronous and that the stack frame that result is in will still be there. You need to alter something that isn't in the stack.

I think this would work

 final Long[] result = new Long[1];

and then

 result[0] = st.getLong(4);

in execute(). At the end, you need to return result[0];


This situation arises a lot in Java, and the cleanest way to handle it is with a simple value container class. It's the same type thing as the array approach, but it's cleaner IMO.

public class ValContainer<T> {
    private T val;

    public ValContainer() {
    }

    public ValContainer(T v) {
        this.val = v;
    }

    public T getVal() {
        return val;
    }

    public void setVal(T val) {
        this.val = val;
    }
}

You need a 'container' to hold your value. You, however, do not have to create a container class. You may use classes in the java.util.concurrent.atomic package. They provide an immutable wrapper for a value along with a set and a get method. You have AtomicInteger, AtomicBoolean, AtomicReference<V> (for your objects) e.t.c

In the outer method:

final AtomicLong resultHolder = new AtomicLong();

In the anonymous inner class method

long result = getMyLongValue();
resultHolder.set(result);

Later in your outer method

return resultHolder.get();

Here's an example.

public Long getNumber() {
   final AtomicLong resultHolder = new AtomicLong();
   Session session = new Session();
   session.doWork(new Work() {
       public void execute() {
           //Inside anonymous inner class
           long result = getMyLongValue();
           resultHolder.set(result);
       }
   });
   return resultHolder.get(); //Returns the value of result
}

Long is immutable. If you use a mutable class, holding a long value, you can change the value. For example:

public class Main {

public static void main( String[] args ) throws Exception {
    Main a = new Main();
    System.out.println( a.getNumber() );
}

public void doWork( Work work ) {
    work.doWork();
}


public Long getNumber() {
    final LongHolder result = new LongHolder();
    doWork( new Work() {
        public void doWork() {
            result.value = 1L;
        }
    } );
    return result.value;
}

private static class LongHolder { 
    public Long value; 
}

private static abstract class Work {
    public abstract void doWork();
}

}