3

I'm using following code :

 public void addConditions(){
    final String arriveHourse, departHourse, arriveMinutes, departMinutes;
    TimePickerDialog.OnTimeSetListener departOnTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
        @Override
        public void onTimeSet(TimePicker timePicker, int selectedHours, int selectedMinutes) {

            departHourse = String.valueOf(selectedHours);
            departMinutes = String.valueOf(selectedMinutes);

        }
    };

...
}

Why the IDE asked me to transform departHourse into final array ?

Why this happened, and how i can avoid that ?

Also if i moved variable outside class, it's work like :

String arriveHourse, departHourse, arriveMinutes, departMinutes;

public void addConditions(){

    TimePickerDialog.OnTimeSetListener departOnTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
        @Override
        public void onTimeSet(TimePicker timePicker, int selectedHours, int selectedMinutes) {

            departHourse = String.valueOf(selectedHours);
            departMinutes = String.valueOf(selectedMinutes);

        }
    };

...
}
Arnold Schrijver
  • 3,588
  • 3
  • 36
  • 65

2 Answers2

4

departHourse is a final variable. It has to be, in order to be used within the anonymous inner class. That means you can't assign a new value to it in the anonymous inner class.

One way around that is to create a single-element array instead:

final String[] valueHolder = new String[1];
...
Foo foo = new Foo() {
    @Override public void bar() {
        valueHolder[0] = "Set in bar";
    }
}

An alternative is to use AtomicReference:

final AtomicReference<String> valueHolder = new AtomicReference<String>();
...
Foo foo = new Foo() {
    @Override public void bar() {
        valueHolder.set("Set in bar");
    }
}

In both cases, this allows you to make new information available without changing the value of the valueHolder variable itself.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • What if I want to change the variable inside the inner anonymous class and return it? I usually face this problem when using the retrofit API for consuming REST APIs. – Kavach Chandra Aug 12 '17 at 08:39
  • 2
    @KavachChandra: You can't do that. The Java language rules explicitly prevent you from using non-final variables in anonymous inner classes. I've shown you two workarounds for that, a third is to just not use anonymous inner classes - create a *named* class and declare a field in it. – Jon Skeet Aug 12 '17 at 08:41
  • some blog said, that due to compiler it self ? is that true? –  Aug 12 '17 at 08:56
  • 1
    @ArduinoAndroid: That question is too vague to answer. – Jon Skeet Aug 12 '17 at 09:00
0

Good description: http://wiki.c2.com/?ClosuresThatWorkAroundFinalLimitation

And the best answer: Lambdas: local variables need final, instance variables don't

Short description: variables are being copied for the anonymous inner class instances (named closures) inside the JVM, so if it would be not final, compiler will need to copy each param.

In your case @override is not the reason you need to declare params final, the reason - they are used as params/local variables in closure!