0

Below code is some example analogous to what I am trying to achieve. I have to store the data from internal class but the compiler complains following:

  returnedValue=(MyXYZClass)value.toString();

Local variable selectedBusinessArea defined in an enclosing scope must be final or effectively final

 private String methodInMainClass(Object someRef){
      String returnedValue="";

      new SomeInnerClass(Object someRef){
          @Override
          public String getData(Object value){
              if(value instanceof MyXYZClass){
                  returnedValue=(MyXYZClass)value.toString(); // Not Happening. I cannot assign it to the outer variable.
              }
              return super.getData(value);
          }
      }

How can I store the value from the overriden method in internal class?

1

3 Answers 3

2

The local variable in your code sample is returnedValue. It has to be final or effectively final but it's neither declared final nor effectively final since it gets a value assigned.

How to solve this:

All you need is final or effectively final variable which can store the state of returnedValue. There are many ways to do it.

One way would be to define a class like BoxedValue.

public class BoxedValue<T> {

    private T value;

    public void set(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }
}

Using it in the code:

private String methodInMainClass(Object someRef){
    BoxedValue<String> returnedValue = new BoxedValue<>("");

    new SomeInnerClass(Object someRef){
        @Override
        public String getData(Object value){
            if(value instanceof MyXYZClass){
                returnedValue.set((MyXYZClass)value.toString()); // Not Happening. I cannot assign it to the outer variable.
            }
            return super.getData(value);
        }
    }

    return returnedValue.get();
}

The variable returnedValue is now effectively final.

If you don't want to define an additional class, you can use any other to store the state, i.e. Optional<String> returnedValue = Optional.of("").

Sign up to request clarification or add additional context in comments.

2 Comments

+1 but the AtomicReference class already does this; docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/…
@user1717259 Yes ... but as you know it actually does more. It has also a more sophisticated interface. I just wanted to keep it simple.
1

You can use an array in order to do the trick

private String methodInMainClass(Object someRef){
      String[] returnedValue= {""};

      new SomeInnerClass(someRef){
          @Override
          public String getData(Object value){
              if(value instanceof MyXYZClass){
                  returnedValue[0] = ((MyXYZClass)value).toString(); // Not Happening. I cannot assign it to the outer variable.
              }
              return super.getData(value);
          }
    }
    // [...]

1 Comment

Because returnedValue reference is never modified, only the first and only element of the array
1

it is not about inner class this also happened in lambda, the you can not change value of var from out of scope of lambda or inner class, otherwise you may make access issue and for multithread race condition, as workaround you may use one of Atomic family classes for that like AtomicReference<T> or AtomicInteger for ex. :

    AtomicInteger count = new AtomicInteger(0);
    Runnable r = () -> {
        count.getAndIncrement();
    };
    r.run();
    System.out.println(count);

Note here that I used only main thread not created new one to not face race condition.

2 Comments

thanks for the answer but we are using unfortunately java 7 . +1 for the answer
@Roxy Atomic family in java from Java 1.5 you still can use it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.