7

好的,据我所知,我了解关于final变量的这些事情。

  1. 它应该只分配一次
  2. 所有final变量都应该在构造函数完成之前初始化

现在使用上述内容,我不明白以下内容如何不起作用:

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正在设置变量。那么为什么编译器会抱怨它呢?

4

5 回答 5

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 - 明确分配。

于 2012-11-20T17:03:57.897 回答
8

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

final字段只能在保证只运行一次的代码块中分配,即构造函数和实例初始化程序。(或在字段的情况下使用静态初始化程序static final。)

更多关于这可以在JLS中找到。

于 2012-11-20T17:03:58.237 回答
3

因为编译器不知道唯一的调用

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

来自构造函数

于 2012-11-20T17:04:05.023 回答
0

应该是以下行

private final otherthing;

就像是

private final Something otherthing;

你错过了课程。

于 2012-11-20T17:04:22.680 回答
0

只是一个旁注:

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

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

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

于 2012-11-20T17:07:37.087 回答