是否可以从从该对象的构造函数调用的Private方法设置最终属性的值?
public class FinalTest {
private final Object a;
//Constructor
public FinalTest() {
setA();
}
private void setA() {
a = new Object;
}
}
对于上面的类,编译器给出了一个错误,说我不能从方法中设置'a'的值。
我理解不可能从构造函数外部为最终变量设置值,但在上面的例子中,我实际上是在构造函数中以某种方式执行它。那么为什么不允许这样做呢?
答案 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初始化时初始化。