我正在阅读Java中的匿名类,它说您可以访问封闭类的方法,但不能访问局部变量。为什么会这样呢?我在说这个:
编辑:较旧的示例是不正确的,不能反映我的意思。根据在“访问封闭类的成员”一节中所写的内容,这应该是一个更好的示例,网址为http://docs.oracle.com/javase/tutorial/java/javaOO/localclasses.html。
public class MyClass {
public interface SomeInterface{
public void someOtherMethod();
}
public void someMethod(int someLocalVar) {
SomeInterface myClass = new SomeInterface(){
public void someOtherMethod(){
someLocalVar = 0; // This must be final to work
}
}
}
}
那么这个限制解决了什么问题呢?
这来自早期版本的Java内部类规范。
链接腐烂的官方规范URL(例如从VM spec
2.14中
引用)已消失:http
:
//java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html
不过,可以在Wayback机器上获得1999年1月17日的快照,相应的规范部分为对局部变量的引用。
事情的工作方式描述如下(我将最相关的语句标记为粗体):
块局部的类定义可以访问局部变量。这使编译器的工作复杂化。这是本地类的先前示例:
Enumeration myEnumerate(final Object array[]) { class E implements Enumeration { int count = 0; public boolean hasMoreElements() { return count < array.length; } public Object nextElement() { { return array[count++]; } } return new E(); }
为了使局部变量对内部类的方法可见,编译器必须将变量的值复制到内部类可以访问它的位置。只要在各处都产生相同的值,对同一变量的引用就可以在不同的地方使用不同的代码序列,因此该名称在其作用域的所有部分中始终表示相同的变量。
按照约定,将局部变量(例如
array
)复制到val$array
内部类的私有字段中。(因为array
是final
,所以这样的副本永远不会包含不一致的值。)
…
您会看到,语言设计者希望每次创建这样的副本时复制的局部变量的值都“一致”。他们的动机很可能是开发人员不必担心在内部类的副本 之外 查看它是否已更改:
Enumeration myEnumerate(Object array[], int copy) { // array not final, let's see...
for (int i = 0, i < 2; i++ ) { // loop to have several copies
class E implements Enumeration {
int count = 0;
public boolean hasMoreElements()
{ return count < array.length; }
public Object nextElement() {
{ return array[count++]; }
} // we hope to be done with E... oh no
array = null; // not final => can change
if (i == copy) {
return new E(); // we need to look outside of E
// to figure value of array it uses
}
}
return null;
}
请注意,尽管规范示例使用命名类,但相同的推理也适用于匿名类:
// ...
for (int i = 0, i < 2; i++ ) { // loop to have several copies
if (i == copy) {
return new Enumeration() {
int count = 0;
public boolean hasMoreElements()
{ return count < array.length; }
public Object nextElement() {
{ return array[count++]; }
} // we hope to be done... oh no
}
array = null; // not final => can change
}
问题内容: 在这里只能是最终的。为什么?如何在不保留为私有成员的情况下重新分配方法? 单击该如何返回? 问题答案: 如注释中所述,其中一些在Java 8中变得无关紧要,在Java 8中final可以隐式使用。但是,只能在匿名内部类或lambda表达式中使用有效的最终变量。 这基本上是由于Java管理闭包的方式。 创建匿名内部类的实例时,该类中使用的任何变量都将通过自动生成的构造函数复制其值。这样避
问题内容: 如何从匿名类的方法内部访问? 问题答案: 如何从匿名类的方法内部访问? 您只需要访问它们即可: 更重要的是:为什么这对您不起作用?
问题内容: 在这里只能是最终的。为什么?如何在不保留为私有成员的情况下重新分配方法? 单击该如何返回?我的意思是, 问题答案: 如注释中所述,其中一些在Java 8中变得无关紧要,在Java 8中final可以隐式使用。但是,只能在匿名内部类或lambda表达式中使用有效的最终变量。 这基本上是由于Java管理闭包的方式。 创建匿名内部类的实例时,该类中使用的任何变量都将通过自动生成的构造函数复制
问题内容: 出于教育目的,我尝试制作一个服务器和一个客户端,其中服务器从多个客户端接收数据并回显每条消息。问题是,当我尝试让服务器一次将回显发送到所有客户端时。 我搜寻并回答了许多类似的问题,但是没有一个对我有帮助。希望你能指出我的错误。提前致谢。 问题答案: 您的嵌套类需要外部类的一个实例,因为它不是静态的-但你不 具备 外部类的一个实例。 尝试制作两个嵌套类。看起来他们无论如何都不 需要 引用
(我一直在重读那个问题标题,思考它看起来有多荒谬,但我向你保证,这是对问题的最佳描述,我有一个实际的应用程序,其中这是最好的结构。我发誓我没有疯。) 考虑以下内容。每个块都是一个单独的文件: 注意,enclosinstance业务是为了解决涉及中间构造函数调用的问题。请参阅“为什么外部类不能扩展内部类?”。 我希望输出为“2”。但是相反,我在System.out.println(a.this.I)
问题内容: 就在今天,我需要一种在不同对象之间传递函数的方法。我很快了解到您不能直接在Java中做到这一点,但是您可以传递一个wht实例,该实例显然被称为“匿名内部类”,如下所示: 定义类: 使其成为一个实例: 并称之为: 很简单。但是我不明白的是为什么它被称为“匿名”。我不只是给它起名字MyCallback吗?命名的东西不能匿名,对吗?请避免对这个术语感到困惑。 问题答案: 不,您说的是MyCa