I have some code like this:
class Outter {
private Bar bar;
[...]
public update() {
provider.doUpdate(new IListenner() {
@Override
public void onSuccess(Bar bar) {
Outter.this.bar = bar;
// Here, Outter.this.bar.equals(bar) is false.
}
}
}
[...]
}
I think this has to do with the way Java capture variables in my closure, capturing a bar reference instead of capturing the Outer instance reference. If I write:
Outter self = Outter.this;
self.bar = bar;
it works, forcing Java compiler to store a reference to my Outter instance instead of a reference to the bar field in its closure.
The right way to do this is probably to use a setBar(Bar bar) in Outter and call it from the inner class.
But as it don't work, why the Java compiler don't give an error message about it ? Like bar should be final when capturing the non-final reference ?
I compile this using Android Studio 1.2.1.1, not tried in other contexts, don't know how Android Studio actually compile Java. My JRE seems to be Java 1.7.0 from the openjdk-7-jre-headless Debian package version 7u79-2.5.5-1~deb8u1.
The behavior you're reporting sounds very strange. First, I can't reproduce it with neither ECJ nor with javac 7. (See http://ideone.com/B4CoQs)
The difference in bytecode between
Outter.this.bar = bar;
and
Outter self = Outter.this;
self.bar = bar;
is just an extra astore_2/aload_2, which basically corresponds to a no-op.
I encourage you to check your assumptions. Perhaps you have a buggy implementation of Bar.equals that causes the confusion.
Like bar should be final when capturing the non-final reference?
Fields aren't captured in that sense. Fields can be accessed from inner classes / methods without being final.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With