0

I have the following code:

  public void visitStrAttribute(String attributeName, Consumer<String> attributeConsumer) {
    IntConsumer intConsumer;
    int stringByteArrayLength = 0;
    visitIntAttribute("", (IntValue) -> stringByteArrayLength = IntValue);
    attributeConsumer
        .accept(new String(readInputStream(stringByteArrayLength), StandardCharsets.UTF_8));
  }

I need to set stringByteArrayLength inside the lambda but an error message appears and it told me Local variable stringByteArrayLength defined in an enclosing scope must be final or effectively final.

How do I fix this?

rgettman
  • 176,041
  • 30
  • 275
  • 357
Salem Masoud
  • 411
  • 11
  • 32
  • You need an object, so that you can change the value of it's property, without having to modify the local variable. – Bhesh Gurung Sep 11 '18 at 14:13
  • Possible duplicate of [Local variable log defined in an enclosing scope must be final or effectively final](https://stackoverflow.com/questions/38402493/local-variable-log-defined-in-an-enclosing-scope-must-be-final-or-effectively-fi) – Nicholas K Sep 11 '18 at 14:13

3 Answers3

1

One solution is to make your variable a final array with one element, and modify the element inside it, like this:

final int[] stringByteArrayLength = {0};
visitIntAttribute("", (IntValue) -> stringByteArrayLength[0] = IntValue);

Although I don't consider it a best practice. I would rather return a new changed value rather than changing it.

Schidu Luca
  • 3,897
  • 1
  • 12
  • 27
1

You have two alternatives here:

  • Create an class to have this attribute, so the object from it will be final, but not the instance variables
  • Make the variable class scope (be careful with multithreading)

These solutions work, but maybe it's not the best option, so to have some inspiration see: Lambdas: local variables need final, instance variables don't

mrdc
  • 93
  • 5
0

Create wrapper:

private static class Integerwrapper {
    private int num;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}

and use as your int.

edit:

You can use int wrapper like: AtomicInteger

Idan Str
  • 614
  • 1
  • 11
  • 33