0

I need to explain why the following code would fail to compile (in terms of scope and lifetime):

class ClassInMethod
{
   public static void main(String[] args)
   {
      int local = 1;

      class Inner
      {
         public void method()
         {
             System.out.println(local);
         }
      }
   }
}

I think it's because: Any local variable used but not declared in an inner class must be declared ‘final’. Thus, in this example ‘local’ must be declared final because its scope and lifetime end within the main method (so needs to be changed to: final int local = 1;).

Any other suggestions?

tommy1370
  • 133
  • 1
  • 2
  • 10
  • 1
    Homework assignment? Have you tried to compile it? ;) – Jonathan Feb 05 '12 at 21:07
  • It is (hence the tag ;); and I have. But actually I think I figured it out- check my post in a ~30secs if you're interested in my second attempt! – tommy1370 Feb 05 '12 at 21:14
  • 2
    This page may help explain _why_ you need the variable to be final: http://techtracer.com/2008/04/14/mystery-of-accessibility-in-local-inner-classes/ – DNA Feb 05 '12 at 21:15

3 Answers3

2

See http://techtracer.com/2008/04/14/mystery-of-accessibility-in-local-inner-classes/ for an explanation of how the compiler uses the final trick to get around problems with inner classes (i.e. scope and lifetime problems).

DNA
  • 42,007
  • 12
  • 107
  • 146
1

Just try to compile it. The compiler outputs:

ClassInMethod.java:11: local variable local is accessed from within inner class; needs to be declared final
    System.out.println(local);
                       ^
1 error
Adam Mihalcin
  • 14,242
  • 4
  • 36
  • 52
1

The reason why you have to make the local variables final is that Java copies their values into the instance of the inner class. What happens behind the scenes is that the compiler generates bytecode that (roughly) corresponds to this:

class ClassInMethod {
    public static void main(String[] args) {
        int local = 1;

        // this happens when you do: new Inner()
        ClassInMethod_main_Inner inner = new ClassInMethod_main_Inner();
        inner.local = local;
    }
}

// the inner class
class ClassInMethod_main_Inner {
    int local;

    public void method() {
        System.out.println(local);
    }
}

If local weren't final, and you could change its value between when Inner is instantiated, and when method() is called, the call to method() would use the old value of local. This would likely be incorrect behaviour. The reason final is mandated is to make the behaviour of inner classes more intuitive.

(There are languages that don't have this restriction, but it requires explicit support from the compiler and runtime. Java's developers have so far not decided to dedicate their effort to implementing it.)

millimoose
  • 39,073
  • 9
  • 82
  • 134