Kind of a silly problem I'm facing here... Basically I'm in a For-loop and within this loop I'm always calling a function to make a button. But in this function I want to pass the loop iterator as it's changing to differentiate the buttons. But then it tells me I need to make the loop iterator "final" which means it doesn't change!
Well my problem will make more sense with some skeleton code:
for(int i = 0; i < appList.size(); i++) {
//some other stuff including creating the below button 'btn'
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//set some attribute based on i
//but when I do this it only sets based on the greatest value of i (!)
}
});
}
Meh kinda silly problem I know... I'm new to Java though!
Cheers.
for(int i = 0; i < appList.size(); i++) {
final int _i = i;
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// use _i instead of i
}
});
}
Consider this bit of silly example code:
int i = 0;
obj.invokeThunkAfter10Seconds(new ThunkObject() {
public void thunk() {
System.out.println(i);
}
}
i = 1;
The ThunkObject
holds a reference to i
, but i
can change, which makes the output unpredictable and depends on when i
is changed and when thunk
is invoked.
Because Java doesn't have proper closures (by design, see Cannot refer to a non-final variable inside an inner class defined in a different method ), you are explicitly not allowed to capture non-final (ie changable) variables like this.
Instead you must declare the variable final
, meaning it's initialized and then is not changable. This means you can never change i
after it has been captured by the inner class.
final int i = 0;
obj.invokeThunkAfter10Seconds(new ThunkObject() {
public void thunk() {
System.out.println(i);
}
}
// Can't change i here. It will forever now be 0.
In your example you can't just set i
to be final, because you do want to change the value on each loop iteration. Instead you can create a copy of the value in a final variable:
for(int i = 0; i < appList.size(); i++) {
//some other stuff including creating the below button 'btn'
final int capturedI = i;
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//set some attribute based on capturedI
}
});
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.