设置最终的类属性

时间:2011-04-07 13:38:27

标签: java immutability final

是否可以从从该对象的构造函数调用的Private方法设置最终属性的值?

public class FinalTest {
  private final Object a;
  //Constructor
  public FinalTest() {
    setA();
  }

  private void setA() {
    a = new Object;
  }
}

对于上面的类,编译器给出了一个错误,说我不能从方法中设置'a'的值。

我理解不可能从构造函数外部为最终变量设置值,但在上面的例子中,我实际上是在构造函数中以某种方式执行它。那么为什么不允许这样做呢?

4 个答案:

答案 0 :(得分:10)

这是不允许的,因为 可以通过其他非构造函数方法调用setA(),这会违反最终保护。由于final是编译时强制操作,因此编译器通过强制初始化在构造函数或内联中​​强制执行final。

在您的简单示例中,所有内容看起来都不错,但如果您稍后将类更新为类似以下内容,则问题会变得更加明显......

public class FinalTest {
  private final Object a;
  //Constructor
  public FinalTest() {
    setA();
  }

  private void setA() {
    a = new Object;
  }

  public void doSomething() {
   this.setA(); // not good because a is final
  }
}

答案 1 :(得分:2)

注意:编译器来假设最坏的情况。通过声明属性“final”,编译器必须确保不能在构造函数之外修改属性。

在使用反射(例如)调用方法的情况下,编译器永远不会看到它。证明某些事情是可能的,而不是不可能的事情要容易得多,这就是编译器按照它的方式工作的原因。

答案 2 :(得分:1)

最终检查在编译时完成,而不是在运行时。在您的情况下,编译器无法确定不会从其他方法调用setA。

答案 3 :(得分:1)

为什么需要从私有方法设置最终变量的值? 你可以这样做:

public class FinalTest {
   private final Object a;
   {
      a=new Object();
   }

   //Constructor
   public FinalTest() {
   }
}

在这种情况下,对象将在每次FinalTest初始化时初始化。