我必须使大部分变量成为最终变量有意义吗?

Does it make sense that I have to make most of my variables final?

在我使用 IntelliJ 检查我的代码后,发出了数百条 "Declaration can have final modifier" 警告。为了解决这些警告,我基本上需要将我的大部分变量变成final,下面是一个典型的例子。这让我想到我应该默认将成员变量设置为 'final' 。在大多数情况下,成员,尤其是容器 类(即 List 或 Set),一旦分配就不会更改。它们通过插入或移除元素在内部发生变化,但对它们的引用不会改变。

public class Attribute {

    private final Insight insight;

    private final Attribute attribute;

    private final List<String> names;

    public Attribute(Insight insight, Attribute attribute) {
        attribute = attribute;
        insight = insight;
        names = new ArrayList<>();
    }
}

在设计中将大多数变量默认设置为 final 有意义吗 类? Java中的'final'是不是可以定义大部分成员变量?

如果您考虑现实世界环境中的大多数应用程序,大多数变量都可以是最终的。将它们声明为 final 有很多好处。 但我建议您养成习惯,而不是使用 IDE 建议和功能。 作为一种习惯,总是考虑变量是否需要变异,如果不是作为定义变量的一部分,只需添加 final。 这种习惯使您独立于 IDE 建议编写决赛。大多数 IDE 都非常擅长代码补全,但你永远不知道。 PS: 养成习惯时,请牢记对象的继承。

我曾经出于习惯不小心声明了一个 final on 方法并为此付出了代价:-)。

如果要重新设计 Java 今天变量可能应该默认为 private 和 final 而不是 package 和 mutable。

可变变量有时是必需的,但只要有可能,您应该更喜欢 final,而且我真的想不出很多合理的理由来将变量设为私有。

对于不同的目标环境,情况可能会有所不同,但 Java 旨在制作好的 readable/maintainable 长寿命代码,考虑到这一点,他们只是在默认设置上做出了一些糟糕的决定。

但它是一种古老的语言,我们不像现在那样了解。生活和学习。

ps:如果我是负责人,我也会抛出已检查的异常……我不是负责人可能是件好事。

虽然每个不更改其初始化引用的成员字段都应该声明为 final 是有道理的,但在您的情况下,您可以使用其他一些最佳实践。您可能希望为您的成员属性提供 setters(和 getters),除非它们在初始化后不可修改。如果您提供 setters,IntelliJ 不会抱怨。此外,您可以按照 here 中列出的说明来抑制这些警告。

简短的回答是

  1. 您应该为您的私有成员属性提供设置器,除非它们不应该被修改。
  2. 如果不应修改它们,请将它们声明为 final

Does it make sense that I have to make most of my variables final?

是的。但它出现的原因可能与该语言在 1990 年代问世时想象的原因不同。

在 90 年代,CPU桌面计算是单核、单线程的。 final 修饰符当时主要用作实现与 C 的 consts 相似语义的手段。

但是 final 现在比 运行 在多线程、多核 CPU 上的程序更重要。通常,尽可能限制 and/or 简化可能在并发环境中共享的对象的状态 space 是有利的。当语言处于早期阶段时,这并不总是很好理解。 Java 早期的 Calendar class(一直持续到 Java 8)有一个非常复杂的状态 space,使用 Calendar 并发环境中的对象比它必须的更难。在他的书 Effective Java(第 2 版)中,Joshua Bloch 甚至说很少有人真正理解 Calendar 的状态 space class.

当实例字段是最终的时,它们可以经历的状态转换次数必然受到限制。这是一件好事,因为这使得并发环境中的对象更易于推理。最终的简单对象是一个不可变对象,其中所有实例字段都以其最终形式初始化并且不能更改。此类对象在并发环境中使用起来非常简单,因为...

  • 它们永远不会在不一致的状态下被观察到,
  • 从不经历状态转换,
  • 从不需要互斥,
  • 从来没有过时的 data/visibility 问题。

因此,不可变对象可以在任意数量的线程之间自由共享。

TL;DR:最终实例字段使您的对象更简单,更容易推理。预期效果是代码更易于理解且维护成本更低。 Bloch 建议您尽可能创建任何实例字段 final