投诉最终变数

时间:2012-11-20 17:02:07

标签: java final

好的,据我所知,我了解final变量的这些内容。

  1. 只应分配一次
  2. 应在构造函数完成之前初始化所有final变量
  3. 现在使用上述内容,我不明白以下内容如何不起作用:

    public class FinalTest implements AnotherClass {
    
        private final Something something;
        private final otherthing;
    
        @Override
        public void setStuff(Something something) {
            this.something = something;
            this.otherthing = new SomeClass(something);
        }
    
        public FinalTest(Something something) {
            setStuff(something);
        }
    }
    

    这里,在构造函数完成之前,正在设置final个变量。那么为什么编译器会抱怨呢?

5 个答案:

答案 0 :(得分:18)

没有必要仅从构造函数调用您的方法,也可以从构造函数外部调用它。甚至第二个调用也可能在将来添加到同一个构造函数中。

即使您现在可能没有使用它,但编译器无法确定它,因此它不允许它。在技​​术术语中,没有definite assignment

例如: - 假设您从main实例化您的课程: -

public static void main(String[] args) {
    FinalTest obj = new FinalTest(something);

    obj.setStuff(something); // There you go. This cannot be prevented. 
}

有关详细说明,请参阅JLS - Definite Assignments

答案 1 :(得分:8)

因为没有人阻止你在对象的生命中第二次调用setStuff(),这将是非法的。

final字段只能在保证只运行一次的代码块中分配,即构造函数和实例初始化程序。 (如果是static final字段,则为静态初始化程序。)

有关详情,请参阅JLS

答案 2 :(得分:3)

因为编译器不知道只能调用

public void setStuff(Something something) {
    this.something = something;
    this.otherthing = new SomeClass(something);
}

来自构造函数

答案 3 :(得分:0)

以下行应

private final otherthing;

类似

private final Something otherthing;
你错过了这门课。

答案 4 :(得分:0)

只是旁注:

@Override
public void setStuff(Something something) {
    this.something = something;
    this.otherthing = new SomeClass(something);
}

public FinalTest(Something something) {
    setStuff(something);
}

这真是一个糟糕的设计。您不应该从构造函数中调用可覆盖的方法。