为什么局部变量不能在内部类中更改?

时间:2016-07-03 01:42:06

标签: java

我将向您展示两个代码群。

    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();
        }
    }

这里我声明了一个全局变量,更改了它的值,声明了一个内部类并创建了这个类的实例。这段代码运行良好并打印

  

1

现在看看这段代码:

        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();
            }
        }

我在第一个代码上做了所有步骤,除了这里变量不是全局变量而是local.Here我得到一个异常,说localVariable必须是final或者有效final.I googled并且理解这就是为什么值被捕获并传递给class的原因。当我们改变它时,类不知道这种变化,它会引起混淆。 我有两个问题:

  

1.如果它引起一些混淆,我们不得在申报后更改它   为什么我们不在全局变量上得到这个例外

     

2.它是关于局部变量值的变化所以我们只有在类实例声明后更改这个值才能得到这个异常。不是吗?

1 个答案:

答案 0 :(得分:1)

1)我认为您的第一个问题由Why a non-final "local" variable cannot be used inside an inner class, and instead a non-final field of the enclosing class can?回答。 (该问题之前被标记为该问题的副本。)请注意,通常,不允许修改变量的规则不适用于作为被引用的对象的一部分的实例字段或数组元素。那些变数。因此,这是合法的:

        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)您的第二个代码段无论如何都无法成功,因为您在为其分配了值之前正在递增localVariable,这违反了有关&#34的规则明确的任务"。至于为什么Java不允许你使用在声明内部类之后未被修改的变量:我不确定。但是,在Java 7及更早版本中,规则是必须声明局部变量(或参数)final才能在内部类中使用它。在Java 8中,这是放松的 - 只要它是有效的最终,你就不必声明变量或参数final。但是,我认为规则是有效的最终,编译器确定变量或参数是否已声明final。在这种情况下,它不可能,因为这是非法的:

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

理论上,Java设计人员可以添加规则,使编译器确定变量是否可以在某个点之后被修改。但那会更复杂,并且它不会获得太多,因为你仍然可以说

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

在使用内部类时,声明一个final变量来保存其他变量的副本是一个相当常见的习惯,至少从我所见过的情况来看。