Java 来自内部类的非最终变量:应该由编译器自动修复吗?

Java 来自内部类的非最终变量:应该由编译器自动修复吗?,java,compiler-construction,inner-classes,Java,Compiler Construction,Inner Classes,当我使用来自内部类的非最终变量时,我有一个编译错误: public static void main(String[] args) { String s = "hello"; s += "world"; Object myObj = new Object() { public String toString() { return s; // compile error } }; System.out.

当我使用来自内部类的非最终变量时,我有一个编译错误:

public static void main(String[] args) {
    String s = "hello";
    s += "world";
    Object myObj = new Object() {
        public String toString() {
            return s; // compile error
        }
    };
    System.out.println(myObj);
}
但是,我可以通过添加一个伪最终变量
tmp
来解决这个问题,该变量引用了我想要访问的另一个变量:

public static void main(String[] args) {
    String s = "hello";
    s += "world";
    final String tmp = s;
    Object myObj = new Object() {
        public String toString() {
            return tmp; // that works!
        }
    };
    System.out.println(myObj);
}
例如,通过编译器,添加临时最终变量的过程可以很容易地自动化


我的问题是:为什么编译器不自动执行允许我们消除此错误的简单更改?

编译器不能用常量替换对局部变量的所有引用,但在构造内部类的实例时,该值会传递给相应的构造函数并存储在变量中。
根据需要,自动实现它是很麻烦的。

我相信这在Java8中是固定的。无法等待…@SuperChafouin答案确实解释了这一点。真正答案的本质是@JonSkeet所说的:通过自动生成的构造函数将值复制到匿名类中的字段。声明类后,它们在本地范围内是无法更改的,因此Java要求它们是最终的,以消除(我猜)任何可能更改的幻觉。@Obicere:Java 8允许您不使用final关键字。但是,如果变量不是有效的final(即,您向它重新分配了新值,正如问题中所做的那样),那么它仍然不会编译。老实说:如果在将新值重新分配给非final变量时代码不会编译,我更喜欢编译器强制final关键字的旧方法。