Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / December 2007

Tip: Looking for answers? Try searching our database.

Anonymous inner Classes accessing final variables?

Thread view: 
rmn190 - 02 Dec 2007 01:48 GMT
Hi

When a write an inner class inside a method , it can access the
variables in the enclosing method if and only if they are final ...
Why is the compiler enforcing this ??

What might be the reason for java doing this ?? Is it that these Local
Variables will be cached for Inner class usage ??

Thanks a lot in advance!
Patricia Shanahan - 02 Dec 2007 01:55 GMT
> Hi
>
[quoted text clipped - 6 lines]
>
> Thanks a lot in advance!

The inner class object may still exist long after the method has
completed. The value it sees for local variables is the value they had
when the object was created.

If non-final variables had been permitted, people would have wasted time
debugging obscure run-time failures due to a variable having changed value.

Note that you can always have a final variable that exists only for the
sake of the inner class object:

{
final int innerValue = someChangingVar;
...
}

Patricia
getsanjay.sharma@gmail.com - 02 Dec 2007 16:36 GMT
> The inner class object may still exist long after the method has
> completed. The value it sees for local variables is the value they had
> when the object was created.
>
> If non-final variables had been permitted, people would have wasted time
> debugging obscure run-time failures due to a variable having changed value.

Hello Patricia,

Can you give a real time example on what kind of complexities can
arise if non-final variables were permitted inside inner classes /
anonymous classes?

Thanks and regards,
/~STS
Daniel Pitts - 02 Dec 2007 18:07 GMT
>> The inner class object may still exist long after the method has
>> completed. The value it sees for local variables is the value they had
[quoted text clipped - 11 lines]
> Thanks and regards,
> /~STS
I sure can.  Imagine this situation:

public void stuff() {
  String foo = "Hello";
  Runnable r = new Runnable() {
    public void run() {
    while (foo.size() < 1000) {
          foo += ".";
        }
    }
  };
  new Thread(r).start();
  System.out.println(foo);
  foo = null;
  return r;
}

So, what is the behavior of this snippet when someone calls "stuff"?  Is
it obvious or did you have to think about it for a while?  Imagine that
the runnable returned was used from some other place in this class?
Signature

Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>

Stefan Ram - 02 Dec 2007 02:17 GMT
>What might be the reason for java doing this ??

     »Guy Steele wrote:

     Actually, the prototype implementation *did* allow
     non-final variables to be referenced from within inner
     classes.  There was an outcry from *users*, complaining
     that they did not want this!«

http://madbean.com/2003/mb2003-49/
Roedy Green - 02 Dec 2007 04:21 GMT
>When a write an inner class inside a method , it can access the
>variables in the enclosing method if and only if they are final ...
>Why is the compiler enforcing this ??

see http://mindprod.com/jgloss/anonymousclasses.html
Signature

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com

Curt Welch - 02 Dec 2007 19:26 GMT
> Hi
>
[quoted text clipped - 6 lines]
>
> Thanks a lot in advance!

I think it's mostly just the issue that the stack frame where the local
variables live won't stay around as long as the inner class object created
will live.  This means it can't work unless the compiler creates code to
allocate a new hidden object to hold the local variables instead of putting
them on the stack so that the local variables could live for as long as the
inner class object lives.

Just because the compiler won't do it for you doesn't mean you can't do it
for yourself like this:

instead of doing:

void someMethod(int a)
{
  int b;
  int c;

  b = a + 2; // use local vars in method
  c = b + 1;

  new Inner() {
     void method() {
       System.out.prinln(a, b, c);  // use local vars in inner class
     }
  }
}

Do it like this:

class LocalVars {
  int a;
  int b;
  int c;
}

void someMethod(int a)
{
 LocalObject locals = new LocalObject();
 locals.a = a;

 locals.b = locals.a + 2;  // use local vars in method
 locals.c = locals.b + 2;

 new Inner() {
   LocalVars locals;
   void setLocal(LocalVars locals) {
      this.locals = locals;
   }
   void method()
   {
      System.out.prinln(locals.a, locals.b, locals.c);  // use local vars
   }
 }.setLocal(locals);
}

The second example is what the compiler would have to do for you every time
you accessed local variables from within an inner class.  Any variable you
access would have to be moved into a local variable object and shared by
both the inner class and the outer method.  That local variable object
would live as long as the method was active, or as long as the inner object
was still alive - whichever lived longer.

In practice, when we need to pass local data into the inner class, we don't
normally create yet another object to hold the local vars but just create
more local vars in the inner class and create setter methods so we can pass
local data into the inner class from the method which created it. Or we put
the data into instance vars of the outer class and make the inner class
access the data in the instance vars instead of accessing local vars.

I'm not sure if Patricia's example of the problems that can arise is really
all that important.  That type of problem can happen no matter how you pass
the data into the inner class.

It's really just a question of whether you want the compiler creating
hidden objects for you without it being obvious in the code you have asked
it to do that.  Stack frames are expected to go away when the method ends,
but to make this work, stack frames would end up living much longer (or at
least the part which was touched by the inner class).  If you create a new
inner class object every time a method is called, the part of the stack
frame which the inner class touched would have to live on as well. It adds
a new dimension of behind-the-scene complexity which is questionable.

The other option is for the compiler to do what it's doing now - treating
the local vars as constants which get compiled into the inner class code or
cached in the inner class object, but do it without the restriction of the
var being final.  This means it makes a copy of the current values of the
local variables at the time the inner class object is created.  That could
work as well, but again, it creates confusion because syntactically that's
not what people would expect to be happening.  They would expect that if
you had a long lived method that the method and the inner class object
would be accessing the same variable instead of different copies of it.  So
that's why they put the final restriction on it - to make it clear because
of how it's implemented, that the inner class and outer method are not in
fact accessing the same variable even though syntactically it looks as if
they are.

Signature

Curt Welch                                            http://CurtWelch.Com/
curt@kcwc.com                                        http://NewsReader.Com/

Wayne - 02 Dec 2007 21:27 GMT
>> Hi
>>
[quoted text clipped - 10 lines]
> inner class object lives.
> ...

Does anyone here know how JavaScript implements closures?  Just curious.

-Wayne


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.