为什么 Java 变量没有更频繁地声明为 `final`?比较 swift 中的 let 关键字

Why isn't Java variable declared as `final` more often? Compare to let keyword in swift

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

在java中,我认为关键字final可以起到同样的作用。但是根据我有限的经验,我只看到人们在极少数情况下将变量声明为 final圆周率。

为什么 Java 变量没有更频繁地声明为 final?有什么我想念的吗?

Java 遵循传统的 C 思维方式,如果我们正在创建某些东西(原始类型或对象),它默认是一个变量,你必须把 put "final" in java 和 "const" in C/C++ 使其成为常量。 Swift 与这些语言相比非常新,其目标是安全的编程模式和简单性。如果您在 Java 中获得更多经验,您就会知道人们确实更频繁地使用最终实践和最佳实践。我认为(正如你也提到的)主要原因是你对 Java.

的接触有限

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 是因为它的语义价值,而另一些开发人员则因为它冗长而不喜欢使用它。

Initialize a variable with final in Java 允许编译器确保你只能初始化它一次。如果是int或者doubles这样的原始类型,可以保证值不能改变。但是,对于Objectfinal只是关于引用本身,而不是关于引用对象的内容。它不保证被引用的对象内部的值保持不变。

比如我可以这样定义一个带有final的List:

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

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

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

public final class Math {

    public static final double PI = 3.14159265358979323846;

Why isn't Java variable declared as final more often? Is there something I'm missing?

你缺少的是"human nature"。

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

请注意,"variables are not final by default" 设计决策来自 Java 的祖先。


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

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

我认为这是因为Java中没有这样的"tradition"。

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

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

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

此外,您必须再写 5 个字符(单词 "final" 加上一个 space)才能在 Java 中声明常量,而在 Swift 中,您不写任何额外的字符(var 和 let 具有相同数量的字符)!程序员是懒惰的,你知道的。

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

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