【问题标题】:Why local variable can not be changed in inner class?为什么不能在内部类中更改局部变量?
【发布时间】:2023-12-27 23:18:01
【问题描述】:

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

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

我在第一个代码上完成了所有步骤,除了这里的变量不是全局的而是本地的。这里我得到一个异常,说 localVariable 必须是最终的或有效的最终的。我用谷歌搜索并理解这就是为什么值被捕获并传递给类的原因。当我们更改它时,类不知道此更改,这会引起混乱。 我有两个问题:

1.如果它引起了一些混乱,我们不必在声明后更改它 为什么我们没有在全局变量上得到这个异常

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

【问题讨论】:

  • 投票重新开放,因为我认为重复项不能回答他的第二个问题。
  • 他不应该有组合问题,而是每个帖子一个问题

标签: java


【解决方案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) 你的第二个代码 sn-p 无论如何都不会成功,因为你在给它赋值之前递增localVariable,这违反了关于“明确赋值”的规则。至于为什么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 变量来保存一些其他变量的副本是使用内部类时相当常见的习惯用法,至少从我所见的情况来看是这样。

【讨论】: