内部类中的非最终变量:是否应该由编译器自动修复?

3
使用内部类时,如果使用非 final 变量,会出现编译错误:
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);
}

这个添加临时最终变量的过程可以很容易地被自动化,例如通过编译器。

我的问题是:为什么编译器不会自动执行这个简单的更改,让我们摆脱这个错误?


1
我相信这个问题在Java 8中已经解决了。迫不及待想要试试... - Obicere
2
@SuperChafouin 这个答案确实解释了那个问题。 - Sotirios Delimanolis
5
真正答案的本质就是@JonSkeet所说的: 值通过自动生成的构造函数被复制到匿名类中的字段。在类被声明后,它们无法在本地范围内改变,因此Java要求它们是final的(我猜是为了消除任何可能会改变它们的幻想)。 - Radiodef
2
@Obicere:Java 8 允许您不使用 final 关键字。但是,如果变量不是有效的 final(即,您重新分配了新值,就像在问题中所做的那样),那么它仍然无法编译。 - JB Nizet
2
说实话:如果在将新值重新分配给非 final 变量时代码无法编译,我更喜欢编译器强制使用 final 关键字的旧方式。 - chzbrgla
显示剩余10条评论
1个回答

0
编译器无法将所有对局部变量的引用替换为常量,但在构造内部类实例时,该值会传递给适当的构造函数并存储在变量中。 根据需要,自动实现它是繁琐的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接