Java 当匿名内部类';它是一个成员,但不是一个变量?

Java 当匿名内部类';它是一个成员,但不是一个变量?,java,Java,很抱歉标题是戈尔,我不知道如何用一句话来描述这个问题。如果你有什么建议,我愿意 假设您有以下类: public class SomeClass { // doesn't even need to be final, which is freaky Runnable memberRunnable = new Runnable() { public void run() { SomeOtherClass.someMethod(memberRun

很抱歉标题是戈尔,我不知道如何用一句话来描述这个问题。如果你有什么建议,我愿意

假设您有以下类:

public class SomeClass {
    // doesn't even need to be final, which is freaky
    Runnable memberRunnable = new Runnable() {
        public void run() {
            SomeOtherClass.someMethod(memberRunnable); // this works
        }
    }
    public void someMethod() {
        final Runnable varRunnable = new Runnable() {
            public void run() {
                SomeOtherClass.someMethod(varRunnable); // compiler error - "varRunnable" might not have been initialized
            }
        }
    }
}
为什么
memberRunnable
能够从
run()
内部访问自身,而
varRunnable
不能?AFAICS这是完全相同的构造

我知道,你显然可以用
这个
。我只是想知道为什么编译器会对这两种看起来完全相同的情况进行区分。这也是为什么它认为
varRunnable
可能没有被初始化的原因,很明显它已经初始化了

有人可能会说,如果
Runnable
是一个类(它是一个接口),那么它的构造函数可能试图调用
run()
,从而实际运行到引用未初始化的场景中。但是,对于
memberRunnable
,情况也应该如此,但这种情况是有效的

有趣的是,如果使用类而不是
Runnable
,则不会发生任何变化,在这种情况下,上述场景(构造函数调用重写的方法)实际上可能会发生。这意味着,在这种情况下,您可以在运行时运行到一个“未初始化的字段”(虽然还没有尝试过),这是相当愚蠢的,因为编译器应该对此加以防范

这也是为什么它认为
varRunnable
可能没有被初始化的原因,很明显它已经初始化了

不,不能保证(在一般情况下)在该点初始化变量

为了论证起见,假设
Runnable
是一个抽象类(而不是接口),而
Runnable
的构造函数调用了
this.run()
。由于
Runnable
的构造发生在赋值之前,这将导致在赋值之前访问
varRunnable

换句话说,它将导致访问未初始化的局部变量。请注意,这比访问尚未显式初始化的字段更糟糕,因为局部变量未初始化为默认值。事实上,更糟糕的是,禁止访问未初始化的局部变量,而允许访问未显式初始化的字段,正如您刚刚发现的那样。(将字段设置为final不会改变这一点。final字段也有默认值,并且它们实际上可以在构造函数中更改(一次)


资料来源:我是一名javac开发人员。

我在问题中指出了这个确切的例子。它没有解释为什么
memberRunnable
可以以同样的方式引用自身。我在最后一句中对此进行了说明。我会尽力澄清。@aioobe如果该成员被声明为
最终成员
?这个示例仍然有效,但不应该,因为它没有默认值。是吗?@Felix,
final
字段的默认值与其他字段相同。Sweet。如果这是reddit,我会给你金子。我没想到这样的问题会在10分钟内得到回答。