为啥 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭]

Posted

技术标签:

【中文标题】为啥 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭]【英文标题】:Why isn't Java variable declared as `final` more often? Compare to let keyword in swift [closed]为什么 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭] 【发布时间】:2016-11-03 12:53:22 【问题描述】:

在swift中,如果变量在初始化后没有变化,建议使用let关键字声明变量。我看到很多变量声明为let

在java中,我认为关键字final可以达到同样的目的。但根据我有限的经验,我只看到人们在极少数情况下将变量声明为final,例如PI。

为什么不经常将 Java 变量声明为 final?我有什么遗漏吗?

【问题讨论】:

因为它是额外的打字并且程序员很懒惰。但是,如果您使用 IDE,它可能会在您保存文件时自动“在可能的情况下添加 final”。 因为人都是懒惰的。 final 在 Java 8 之前对于闭包是必需的,但除此之外很少使用。我和Robert Simmons Jr. 主张它的采用率更高。主要原因是它确实在编译时过滤掉了一些愚蠢的错别字。但由于它对程序运行时间没有影响,与 C++ 中的const 不同,对于额外的打字和代码噪音,没有足够强大的(对许多人而言)论据。 是的,你应该这样做。它清楚地表明了您的意图(不想意外更改值)。您与编译器交流的每一个意图都有助于捕获错误(与 @Override 相同的参数——可能应该是强制性的和/或关键字,但现在为时已晚,语言已经过时了)。 请注意:这不是一个好问题;你基本上是在询问意见。我的两分钱:您想让尽可能多的字段(静态或非静态)最终化;但我个人不参与将 final 放在方法参数或局部变量上的业务。 @Jägermeister:嗯,对于字段,大多数开发人员会同意使用 final 很有用。但是对于参数和局部变量,不同的开发者有不同的看法。因此,这个问题的答案不一定是关于意见,而是指出存在不同意见。 【参考方案1】:

见In Java, should I use “final” for parameters and locals even when I don't have to?

基本上,对于字段来说,它是有用的并且还会改变它们的并发属性。 见Java concurrency: is final field (initialized in constructor) thread-safe?

但是,对于局部变量和参数,final 的值不太清楚。它有一些语义价值,但另一方面,它也可能是噪音

public void foo (final int x, final int y)
    try
        final int z = x+y;
    
    catch (final Exception z)
        final String message = "";
        throw new RuntimeException(message);
    

相比

public void foo (int x, int y)
    try
        int z = x+y;
    
    catch ( Exception z)
        String message = "";
        throw new RuntimeException(message);
    

如果你有简短的方法(你通常应该有),那么很明显变量没有被改变。

因此,一些开发人员更喜欢使用 final 的语义值,而另一些开发人员则不喜欢使用它,因为它很冗长。

【讨论】:

“而其他人不喜欢使用它,因为它很冗长”。对于许多人来说,这适用于整个 Java :-) @Thilo:确实如此,但由于 Java 已经非常冗长,因此您不必在不必要时使其更加冗长 :)【参考方案2】:

Java 遵循传统的 C 思维方式,如果我们创建某些东西(原始类型或对象),默认情况下它是一个变量,您必须在 java 中放入“final”,在 C/C++ 中放入“const”才能实现一个常数。与这些语言相比,Swift 是非常新的,它的目标是安全的编程模式和简单性。如果您在 Java 方面获得更多经验,您就会知道人们确实更经常地使用最终实践和最佳实践。我认为(正如您也提到的)的主要原因是您对 Java 的了解有限。

【讨论】:

【参考方案3】:

为什么不经常将 Java 变量声明为 final?我有什么遗漏吗?

你缺少的是“人性”。

简单地说,Java 的语法使不添加final 变得更容易。一般来说,人们不会这样做,因为不这样做更容易。

请注意,“变量默认不是最终的”设计决策来自 Java 的祖先。


当然,这并没有解决您隐含的问题,即 Java 程序员应该更频繁地使用final1。但这是一个意见问题,*** 不鼓励基于意见的问答。

1 - .... 在适当的情况下。在变量显然需要可变的情况下使用 final 会适得其反。

【讨论】:

这也适用于类和方法,有人说默认应该是final 是的......虽然这是一个不同的问题。在那里,您正在处理由于继承导致的抽象破坏问题。 @shmosel 您应该尽可能声明方法final(只要您不会覆盖它)。否则它们默认是虚拟的并且有性能损失。 @StephenC 你能告诉我在哪里可以问这种与编程相关的基于意见的问答吗? @XiaojunChen - 这是不正确的。 JIT 编译器会处理这个问题。【参考方案4】:

在 Java 中使用 final 初始化变量允许编译器确保您只能初始化一次。如果是intdoubles这样的原始类型,则可以保证值不能改变。但是,对于Objectfinal 仅与引用本身有关,与被引用对象的内容无关。它不保证被引用的对象内部的值保持不变。

例如,我可以用 final 定义一个 List 如下:

final List<String> foo = new ArrayList<String>();

上面的List foo 不能再次初始化,但它的内容可以改变,即它不会使foo 不可变。因此,这会使 final 关键字的用处降低。

final 关键字在声明一个常量值时占有一席之地,尤其是当类中只需要一个使用static 关键字的实例时。以下是java.util.Random.Math 中的示例:

public final class Math 

    public static final double PI = 3.14159265358979323846;

【讨论】:

【参考方案5】:

我认为这是因为 Java 中没有这样的“传统”。

你看,我读的第一本关于 Swift 的书(Apple Inc. 的 The Swift Programming Language 2.0)说,你创建的每个没有变异的变量都应该声明为 let 常量。

由于 The Swift Programming Language 2.0(本书)是 Swift 的官方指南,因此几乎每个人都遵循它。即使人们不读那本书,他们也会读读过那本书的人写的教程。结果大家的编码风格都是这样的。

相比之下,我读过的第一本关于 Java 的书(傻瓜用 Java 编程)并没有强调如果值不会改变我们应该使用 final。官方文件也很少这样做。所以只有少数程序员遵循这条规则。这导致大多数人编写的代码实际上都遵循此规则。

此外,在 Java 中,你必须多写 5 个字符(单词“final”加上一个空格)来声明一个常量,而在 Swift 中,你不需要写任何额外的字符(var 和 let 有相同的数字)字符)!程序员很懒,你知道的。

【讨论】:

【参考方案6】:

至少根据我的经验,如果变量在启动后没有改变,建议使用final。对于原始类型,JVM 会将其视为常量并进行一些优化。

在其他情况下,例如在 Java 中,所有方法默认情况下都是虚拟的,除非声明为 final。它还将获得计算性能。

【讨论】:

以上是关于为啥 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

String

java中的final类是不是与所有方法都声明为final且所有变量都声明为private的类相同[重复]

Java final关键字

为什么java内部类访问局部变量必须声明为final?

Java面试基础知识

java经典面试题