6

Possible Duplicate:
Cannot refer to a non-final variable inside an inner class defined in a different method

Why it's impossible in java to refer non-final variable in inner anonymous class? Simple answer would be "Because it's prohibited", but I'd like to know, WHY did they prohibit this useful functionality? Maybe there are some sort of abilities Java lacks of or it's designed in the "wrong" way. I'd like to know.

Community
  • 1
  • 1
dhblah
  • 9,751
  • 12
  • 56
  • 92
  • Look at this post, it may help a bit: http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a-different – mandubian Jul 12 '11 at 10:36
  • 1
    Answered here: http://stackoverflow.com/questions/1299837/cannot-refer-to-a-non-final-variable-inside-an-inner-class-defined-in-a-different – Jacob Jul 12 '11 at 10:36
  • @cularis, I've looked over it but due to edits it's not clear what answer to consider correct. – dhblah Jul 12 '11 at 10:40
  • Another good answer here : http://stackoverflow.com/questions/4785073/why-should-my-local-variables-be-final-to-be-accessible-from-anonymous-class/4785141#4785141 – Ishtar Jul 12 '11 at 11:03

1 Answers1

3

The reason is that after the enclosing method returns, the local variable no longer exists. Therefore a copy of the variable is created when the anonymous class is instanciated. If Java allowed the local variable to be changed afterwards, the anonymous class would only know the old value.

The way Java does it is opposed to real closures known from other languages.

Mathias Schwarz
  • 7,099
  • 23
  • 28
  • 2
    As I see it, the prohibition exists to maintain the illusion that the anonymous class uses the variable directly rather than a copy, and to avoid people having false expectations. – Michael Borgwardt Jul 12 '11 at 10:41
  • Thanks for your answer, but I'm not sure that variable is copied, due to you can perfectly pass final variable, then change one of its fields inside anonymous and that change will be visible in the enclosing method. – dhblah Jul 12 '11 at 10:44
  • 1
    `final` only means that the reference cannot be changed, not that the object suddenly becomes immutable. Only the reference is copied, not the object itself (the object is stored in the heap, not on the stack). – Mathias Schwarz Jul 12 '11 at 10:48
  • 'I'm not sure that variable is copied'. You are mistaken. It is. The original can go out of scope, so it *must* be copied. – user207421 Jul 12 '11 at 10:49
  • @EJP: well, languages that support true closures manage to do it without copying the variable. Admittedly that involves a lot of behind-the-curtains magic; AFAIK stack frames that are referred to by a closure are actually allocated on the heap and thus become scope-independant. – Michael Borgwardt Jul 12 '11 at 11:02
  • @Michael Borgwardt Of course, but this is Java ... – user207421 Jul 12 '11 at 11:13
  • @EJP, yes, it is, but if the variable will be changed afterwards in the enclosing method, this change WILL be visible inside the closure, because both variables refer to the same object. – dhblah Jul 12 '11 at 12:06
  • @gasan But it *can't* be changed, *because* this is Java, and the Java compiler insists that it be final, so it can't be changed. This is what we are discussing. – user207421 Jul 13 '11 at 07:04
  • @gasan: The reference is copied, not the object. final behaves the same way in anonymous classes as anywhere else. Perhaps you can think of the final variables as parameters to a (hidden) constructor of the anonymous class. – Mathias Schwarz Jul 13 '11 at 07:09
  • @EJP I meant object behind that variable, not variable itself can be changed – dhblah Jul 13 '11 at 09:21
  • @Mathias thanks, at first I thought that the object is copied. – dhblah Jul 13 '11 at 09:22
  • @gasan your point eludes me. The final outer variable is copied into the inner class. Period. Nothing you have said subsequently alters or even bears on that fact. – user207421 Jul 13 '11 at 09:49
  • @EJP To make myself clear: variable from enclosing code is copied into the closure that variable into the closure can be changed, also can be changed the object that is referred to outer and inner variable. Changing in copied variable won't affect outer variable. – dhblah Jul 13 '11 at 11:17
  • @gasan None of this affects the invalidity of your statement 'if the variable will be changed afterwards in the enclosing method, this change WILL be visible inside the closure'. This cannot happen in Java. – user207421 Jul 14 '11 at 10:24