0

I will show you two code bunchs.

    public class A {

        int globalVariable;


        public void foo() {
            globalVariable++;
            class B {
                void foo() {
                    System.out.println(globalVariable);
                }
            }

            B b = new B(); 
            b.foo(); 
        }

        public static void main(String[] args) {
            A a = new A();
            a.foo();
        }
    }

here i declared one global variable, changed its value, declared one inner class and created instance of this class.This code will work well and print

1

Now check out this code:

        public class A {

            public void foo() {
                int localVariable;
                localVariable++;
                class B {
                    void foo() {
                        System.out.println(localVariable);
                    }
                }

                B b = new B();
                b.foo();
            }

            public static void main(String[] args) {
                A a = new A();
                a.foo();
            }
        }

i did all steps on first code except here variable is not global but local.Here i get an exception that says localVariable must be final or effectively final.I googled and understood that this is why value gets captured and passed to class.When we changed it class doesn't know about this changes and it cause confusing. i have 2 questions:

1.if it cause some confusing and we have to not change it after declaration why we don't get this exception on global variable

2.it it is about local variable value changes so we have to get this exception only if we change this value after class instance declaration.Isn't it?

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
Sarkhan
  • 1,281
  • 1
  • 11
  • 33

1 Answers1

1

1) I think your first question is answered by Why a non-final "local" variable cannot be used inside an inner class, and instead a non-final field of the enclosing class can?. (The question was earlier marked as a duplicate of that one.) Note that in general, the rule about not being allowed to modify variables doesn't apply to instance fields, or array elements, that are part of an object referenced by those variables. Therefore, this is legal:

        public void foo() {
            int[] localVariable = new int[1];
            localVariable[0]++;
            class B {
                void foo() {
                    System.out.println(localVariable[0]);
                }
            }

            B b = new B();
            b.foo();
        }

2) Your second code snippet can't succeed anyway, because you're incrementing localVariable before you've assigned a value to it, and that breaks the rules about "definite assignment". As for why Java doesn't let you use a variable that isn't modified after the inner class is declared: I don't know for sure. However, in Java 7 and earlier, the rule was that a local variable (or parameter) had to be declared final in order for it to be used in an inner class. In Java 8, this was relaxed--you didn't have to declare a variable or parameter final, as long as it was effectively final. However, I think the rule is that to be effectively final, the compiler determines whether the variable or parameter could have been declared final. And in this case, it can't, because this is illegal:

        public void foo() {
            final int localVariable = 3;
            localVariable++;
        }

In theory, the Java designers could have added rules to make the compiler determine whether a variable could be modified after a certain point. But that would have been more complicated, and it wouldn't have gained much, since you can still say

        public void foo() {
            int localVariable = 3;
            localVariable++;
            final int finalLocalVariable = localVariable;
            class B {
                void foo() {
                    System.out.println(finalLocalVariable);
                }
            }
        }

Declaring a final variable to hold a copy of some other variable is a fairly common idiom when using inner classes, at least from what I've seen.

Community
  • 1
  • 1
ajb
  • 31,309
  • 3
  • 58
  • 84