内部类如果要引用外部类的变量,则该变量必须为final
2011-12-12 10:20
204 查看
今天程序中突然贵蹦出来一个这么错误:
Cannot refer to a non-final variable service inside an inner class defined in a different method
上网查最一下才知道:
内部类引用了一个非final的变量,
内部类如果要引用外部类的变量,则该变量必须为final,这是规定
(我觉得应该是生命周期的问题! 如果你引用的外部变量不是一个final 的! 那么,可能在你的内部类运行期间 引用的外部变量 超出了生命周期之外(方法执行完了 ,可是内部类对象却还在引用该局部变量!))
涉及到闭包(closure)的概念。
不同语言对闭包选择了不同的支持,相比之下,C#中就能够在匿名函数中引用非final的外部变量,例如这篇帖子中提到的C#代码:
这一行:
就在匿名方法内引用了外部局部变量: variable.
但同时也引起了一个奇怪的问题,上面的C#代码,我们期望的结果应该是输出"0, 2, 4, 6, 8"才对,结果却是10个零。
原因就是C# compiler 在所闭的包内圈入了对variable的引用,然后当运行
时,variable值已经变成5,结果输出为10个零。
这种特性多少有点令人意外,可能java正是为了避免这种情形,于是强制规定闭包内引用的外部局部变量必须为final,想象一下如果上例中variable 为final的话,自然就不会写出上面的代码,造成类似的意外了。
另外,上例中如果你希望达到输出"0, 2, 4, 6, 8"的效果,可以:
Cannot refer to a non-final variable service inside an inner class defined in a different method
上网查最一下才知道:
内部类引用了一个非final的变量,
内部类如果要引用外部类的变量,则该变量必须为final,这是规定
(我觉得应该是生命周期的问题! 如果你引用的外部变量不是一个final 的! 那么,可能在你的内部类运行期间 引用的外部变量 超出了生命周期之外(方法执行完了 ,可是内部类对象却还在引用该局部变量!))
涉及到闭包(closure)的概念。
不同语言对闭包选择了不同的支持,相比之下,C#中就能够在匿名函数中引用非final的外部变量,例如这篇帖子中提到的C#代码:
List<Func<int>> actions = new List<Func<int>>(); int variable = 0; while (variable < 5) { actions.Add(() => variable * 2); ++ variable; } foreach (var act in actions) { Console.WriteLine(act.Invoke()); }
这一行:
actions.Add(() => variable * 2);
就在匿名方法内引用了外部局部变量: variable.
但同时也引起了一个奇怪的问题,上面的C#代码,我们期望的结果应该是输出"0, 2, 4, 6, 8"才对,结果却是10个零。
原因就是C# compiler 在所闭的包内圈入了对variable的引用,然后当运行
Console.WriteLine(act.Invoke());
时,variable值已经变成5,结果输出为10个零。
这种特性多少有点令人意外,可能java正是为了避免这种情形,于是强制规定闭包内引用的外部局部变量必须为final,想象一下如果上例中variable 为final的话,自然就不会写出上面的代码,造成类似的意外了。
另外,上例中如果你希望达到输出"0, 2, 4, 6, 8"的效果,可以:
while (variable < 5) { int copy = variable; actions.Add(() => copy * 2); ++ variable; }
相关文章推荐
- 一个注意事项:内部类引用的外部变量必须是final的
- 内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例
- 内部类引用外部类中的局部变量时,该变量需final
- 内部类中引用的变量必须要声明为final的原因
- java内部类引用外部类的变量时必须是final变量
- 关于匿名内部类和局部内部类的外部引用必须是final的疑问
- java匿名内部类使用外部变量时,外部变量必须是final,为什么?
- 内部类引用局部变量为什么要求必须是final的,而引用全局变量就不需要
- 引用一个面试题:如果程序中没有任何变量引用一个外部类对象,但有变量引用其中的内部类对象,请问外部类对象是否会被垃圾回收器回收?请说明理由!
- java 内部类 外部局部变量必须 final 原因
- 内部类引用外部类局部变量,外部类局部变量必须是final
- java匿名内部类使用外部变量时,外部变量必须是final,为什么?
- java匿名内部类使用外部变量时,外部变量必须是final,为什么?
- 为什么匿名内部类中用外部类的成员变量,外部类的成员变量必须是final
- java内部类引用外部类中的变量 必须是final
- 为什么内部类调用外部变量,外部变量必须用final修饰
- 解析——java匿名内部类使用外部变量时,外部变量必须是final
- Java 局部 final 变量与内部类引用外部变量
- 匿名内部类引入外部变量必须是final?
- Java 匿名内部类中的外部引用为什么必须是 final 的?