【问题标题】:Why instance variable to be final?为什么实例变量是最终的?
【发布时间】:2015-03-23 20:52:21
【问题描述】:

我阅读了this question 关于不可变对象的内容,但留下了一个关于不可变对象和最终字段的问题:

为什么我们需要不可变类中的实例变量是最终的?

例如,考虑这个不可变的类:

public final class Immutable 

{

  private final int someVal;

  public Immutable(int someVal)
 {

    this.someVal= someVal;
  }

  public int getVal() {

    return val;
}

}

如果在上面的代码中没有设置方法,并且实例变量只在构造函数中设置,为什么要求实例变量声明为final?

【问题讨论】:

  • 再次阅读引用的问题,不是实例变量必须是最终的,而是类。
  • 是的,我读到了,但我的问题是为什么该类中的实例变量应该是最终的?
  • 也许是这样:它没有必须是最终的,但它应该是最终的(明确表明它不会是修改)。
  • @Marco13 不需要将实例变量设为最终变量,但我需要将其设为最终变量。所以这只是编码的一个好习惯

标签: java immutability final


【解决方案1】:

没有要求来生成变量final。但是,当您确实明确打算永远不更改变量时,将其设为final 通常是一种好习惯,因为这不仅可以强制执行不变量以防止拼写错误或其他错误,而且还声明了它是不可变的意图例如,其他程序员或您自己。

如果变量是public,那么您将严格需要将其设为final,以确保接口代码无法更改其值。

请注意,您链接的问题没有直接关系,因为它讨论的是final 的类,而不是变量。创建一个类final 意味着它不能被继承,而不是它是不可变的。但是,在制作不可变对象时,肯定有必要注意该问题的内容及其答案。但它仍然是一个单独的问题。

【讨论】:

    【解决方案2】:

    通过标记类的所有字段final,您可以清楚地表明您希望您的类是不可变的。

    假设你有以下类:

    public class Immutable {
        private int value;
    
        public Immutable (int value) {
            this.value = value;
        }
    
        public int getValue () {
            return value;
        }
    }
    

    没有 setter 方法,因此可以很容易地假设这个类是不可变的。就目前而言,它是什么。但最终你的类会被其他程序员修改,而这个程序员可能会在你的类中添加一些方法:

    public class Immutable {
        private int value;
    
        public Immutable (int value) {
            this.value = value;
        }
    
        public int getValue () {
            return value;
        }
    
        public void doSomething () {
            value++;
        }
    }
    

    如果字段不是final,很容易无意中添加修改对象状态的方法。通过将它们标记为final,这个其他程序员在尝试修改该字段时会得到一个编译错误,并且不得不问自己为什么这个字段是final,他的修改是否违反了这个类的约定。

    有人可能会争辩说,应该使用 Javadoc 来记录所述类是不可变的,但坦率地说,并不是每个人都阅读 Javadoc。在我看来,让代码自己说话会更好。

    【讨论】:

    • 从编程的角度来看,这是一个很好的解释,例如我的代码在一段时间后被替换。
    • 在您链接到的问题中,将您的班级标记为final 非常重要,您应该考虑到这一点。
    【解决方案3】:

    在不可变类中,您不能更改其属性/字段的状态。通常它是通过不向类的客户端代码提供 setter 方法来完成的。

    并且static final关键字的组合用于使变量成为常量。声明为 final 的变量一旦被初始化就永远不能改变它的值。

    由于在不可变类中您永远不需要更改属性/字段状态,因此最好将其设为 final。

    【讨论】:

      【解决方案4】:

      前面的答案是错误的。

      要成为不可变对象,必须将所有属性声明为 final。

      当线程之间存在数据竞争时,Java 内存模型为 final 字段提供了某些保证,以防止它们返回不正确的默认值。

      参见https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5-110 中的示例 17.5-2。

      【讨论】:

      • 在这里解释你的答案链接不够
      • 不要只提供链接哥们。也解释一下。
      猜你喜欢
      • 2014-06-20
      • 2021-03-21
      • 1970-01-01
      • 1970-01-01
      • 2010-10-21
      • 1970-01-01
      • 2011-04-24
      • 2015-02-24
      • 1970-01-01
      相关资源
      最近更新 更多