我必须让我的大部分变量最终成功吗?

时间:2017-10-05 23:38:24

标签: java intellij-idea final

在我使用IntelliJ检查我的代码后,会发出数百个“声明可以有最终修饰符”的警告。要解决这些警告,我基本上需要将大部分变量转换为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”?

4 个答案:

答案 0 :(得分:3)

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

可变变量有时是必要的,但是只要有可能你应该更喜欢final,我真的不能想到许多合理的理由让变量变成私有变量。

对于不同的目标环境,情况可能会有所不同,但Java旨在提供良好的可读/可维护的长期代码,考虑到这一点,他们只是在默认情况下做出了一些不好的决定。

但这是一种古老的语言,我们现在所知道的并不多。生活和学习。

ps:如果我负责的话,我也会抛弃检查过的例外......我可能不是一件好事。

答案 1 :(得分:1)

如果您考虑在现实环境中的大多数应用程序,大多数变量都可以是最终的。宣布最终结果有很多好处。 但我建议你这样做,而不是使用IDE的建议和功能。 习惯总是想到变量是否需要变异,如果不是定义变量的一部分,只需添加final。 这种习惯使你可以独立于IDE建议编写决赛。大多数IDE都非常擅长代码完成,但你永远不会知道。 PS:当你养成这个习惯时,请记住你的物品的继承。

我偶然宣布一个习惯性的最终方法,并为此付出代价: - )。

答案 2 :(得分:1)

  

我必须让我的大多数变量最终成功吗?

是。但其原因可能与20世纪90年代语言出现时所想象的原因不同。

在90年代,桌面计算中的CPU是单核,单线程。当时主要使用final修饰符作为实现与C的const类似语义的方法。

但是final现在更重要的是程序运行在多线程,多核CPU上。通常,在可能的情况下限制和/或简化可以在并发环境中共享的对象的状态空间是有利的。当语言处于早期阶段时,这并不总是很好理解。早期Java中的Calendar类(持续到Java 8)具有非常复杂的状态空间,具有同样复杂的状态转换,这使得在并发环境中使用Calendar对象比以前更困难。 Joshua Bloch在他的书“ Effective Java ”(第二版)中甚至说很少有人真正理解Calendar类的状态空间。

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

  • 永远不会在不一致的状态下观察到它们,
  • 永远不会进行状态转换,
  • 永远不要求互相排斥,
  • 永远不会有陈旧的数据/可见性问题。

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

TL; DR:最终实例字段使您的对象更简单,更容易推理。预期的影响是代码更容易理解,维护成本更低。布洛赫建议您尽可能使用任何实例字段final

答案 3 :(得分:0)

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

简短的回答是

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