Anonymous inner Classes accessing final variables?

Discussion in 'Java' started by rmn190, Dec 2, 2007.

  1. rmn190

    rmn190 Guest

    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!
    rmn190, Dec 2, 2007
    #1
    1. Advertising

  2. rmn190 wrote:
    > 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!


    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
    Patricia Shanahan, Dec 2, 2007
    #2
    1. Advertising

  3. rmn190

    Stefan Ram Guest

    rmn190 <> writes:
    >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/
    Stefan Ram, Dec 2, 2007
    #3
  4. rmn190

    Roedy Green Guest

    On Sat, 1 Dec 2007 17:48:28 -0800 (PST), rmn190 <>
    wrote, quoted or indirectly quoted someone who said :

    >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
    --
    Roedy Green Canadian Mind Products
    The Java Glossary
    http://mindprod.com
    Roedy Green, Dec 2, 2007
    #4
  5. rmn190

    Guest

    On Dec 2, 6:55 am, Patricia Shanahan <> wrote:
    > 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
    , Dec 2, 2007
    #5
  6. rmn190

    Daniel Pitts Guest

    wrote:
    > On Dec 2, 6:55 am, Patricia Shanahan <> wrote:
    >> 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

    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?
    --
    Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
    Daniel Pitts, Dec 2, 2007
    #6
  7. rmn190

    Curt Welch Guest

    rmn190 <> wrote:
    > 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!


    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.

    --
    Curt Welch http://CurtWelch.Com/
    http://NewsReader.Com/
    Curt Welch, Dec 2, 2007
    #7
  8. rmn190

    Wayne Guest

    Curt Welch wrote:
    > rmn190 <> wrote:
    >> 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 ??
    >> ...

    >
    > 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.
    > ...


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

    -Wayne
    Wayne, Dec 2, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. lonelyplanet999
    Replies:
    1
    Views:
    2,216
    VisionSet
    Nov 13, 2003
  2. VisionSet
    Replies:
    4
    Views:
    487
    Bent C Dalager
    Dec 5, 2003
  3. Scott Simpson
    Replies:
    8
    Views:
    1,027
    Stefan Ram
    Jan 13, 2006
  4. Carlo v. Dango
    Replies:
    14
    Views:
    1,031
    Alex Martelli
    Oct 19, 2003
  5. Pyenos
    Replies:
    2
    Views:
    386
    Pyenos
    Dec 27, 2006
Loading...

Share This Page