【问题标题】:Use of final local variables in java [duplicate]java中最终局部变量的使用[重复]
【发布时间】:2013-08-16 01:00:25
【问题描述】:

我想知道使用最终局部变量是否有用。当继承出现时,变量无论如何都不会被覆盖。例如下面的简单代码

public static void main(String args[]) {
    final String data = "Hello World!";
    System.out.println(data);
}

这个例子很简单,可能不是相关代码,但问题更笼统。我见过很多代码(所有代码都包含在具有最终局部变量的主函数中)是否有声明局部变量的可用性除了它们不能在同一个函数本身中编辑之外,它们是最终的吗?

【问题讨论】:

  • 你为什么需要它?您可以使用硬编码或在类中使用私有 final

标签: java final local-variables


【解决方案1】:

java中final局部变量的使用

final 字段、参数和局部变量是只读的(表示对象的身份,而不是其状态)。

【讨论】:

  • 当然,但是任何值得一提的编译器都会认识到变量在方法内部永远不会改变,并将其视为已声明为 final 的变量。唯一的好处是:阅读或修改代码的人会知道作者的意图,并且可以防止您意外地重新分配值。
  • 用final标记的变量或引用类型应该并且必须在编译之前初始化,否则编译失败。
【解决方案2】:

是的,有一个小例子,我们可以正常使用它 -

片段

final Boolean data = Boolean.TRUE;
button.addListener(SWT.Selection, new Listener() {
    public void handleEvent(Event event) {
        if (data ) {
                     ....
                }
        }
});

这是一个使用匿名内部类的例子。如果你想在内部类中使用你的局部变量,你必须使final

【讨论】:

    【解决方案3】:

    Jon Skeet 的完美答案,但最终变量还有另一个(小)好处。

    编译器将确保最终变量设置一次且仅一次。

    假设您必须初始化一个变量并且该值的计算很复杂(if-then-else 中的多个 if-then-else)。您可能会编写在某些情况下不初始化变量的代码(或将其初始化两次)。当然,这是一个错误。使变量为 final 将允许编译器检查最终变量是否设置一次且仅一次。因此,如果您有错误,您会很快知道。

    正如我所说,好处不大,但仍然很方便。

    【讨论】:

      【解决方案4】:

      是的,可用性是:- 方法内部类可以访问局部最终变量。 由于局部变量存在于堆栈上并且仅在方法的生命周期内存在,但内部类对象可能存在更长的时间,因此内部类无法访问任何非最终局部变量。 但是一旦变量是最终的,那么内部类会确保该值不会改变,因此它会保留最终局部变量的私有副本以供使用。

      【讨论】:

      • 这是我发现的唯一合理合适的答案。好一个@Krushna
      【解决方案5】:

      它告诉其他程序员,编写它的人知道 data 的值一旦分配就不应改变。在我看来这是一个好习惯,尤其是将参数变量声明为 final

      【讨论】:

        【解决方案6】:

        您可以使用 final 关键字来提高可读性并确保它没有被修改或在匿名类中,例如这里:

            final String s = "hi";
            new Thread(new Runnable() {
                @Override
                public void run() {
                    // can use s variable here
                }
            }).start();
        

        【讨论】:

          【解决方案7】:

          final 局部变量可以从匿名内部子类访问,而非 final 局部变量则不能。

          【讨论】:

            【解决方案8】:

            首先,关于变量被“覆盖”的部分 - final 有两个非常不同的含义。对于类和方法,它是关于继承的;对于变量,它是关于只读的。

            final 局部变量有一个重要的“特性”:它们可以在本地(通常是匿名的)内部类中使用。非最终局部变量不能。根据我的经验,这是 final 对局部变量的主要用途。

            public void foo() {
                final String x = "hello";
                String y = "there";
            
                Runnable runnable = new Runnable() {
                    @Override public void run() {
                        System.out.println(x); // This is valid
                        System.out.println(y); // This is not
                    }
                };
                runnable.run();
            }
            

            请注意,作为一种风格,有些人喜欢使用final,即使他们在本地内部类中捕获变量。我当然愿意 final 作为默认值,但“非最终”的修饰符不同,但我发现在任何地方显式添加修饰符太分散注意力了。

            【讨论】:

            • 我也觉得它有助于执行优化。由于这个 final 变量的值不会改变,JVM 会缓存这个变量的值以提高性能。
            • @Ankur 很久没有这样了。编译器可以很容易地计算出变量是否更改并相应地进行优化。这是another SO answer 的意思。
            • @Jon Skeet 假设这些变量存在于它们的本地范围之外是否正确,因为它们可以被匿名内部类访问?
            • @Ahmed:在幕后,编译器在匿名内部类中生成一个实例变量,并在创建实例时复制原始变量的值。与考虑超出其本地范围的原始变量相比,这对您是否有用是您的电话:)
            • @JonSkeet 感谢您的清晰解释 :) 我想了解编码时幕后发生的事情。
            猜你喜欢
            • 1970-01-01
            • 2012-05-27
            • 1970-01-01
            • 1970-01-01
            • 2011-11-25
            • 1970-01-01
            • 2020-04-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多