Instance Initializer与私有成员

Aja*_*jay 4 java initialization

我有以下代码: -

public class Test5 {
    private int value ;
    public static void main(String[] args) {
        Test5 a, b;
        a = new Test5();
        b = new Test5(){{ value = 1 ;}};
    }
}
Run Code Online (Sandbox Code Playgroud)

以下行显示错误: -

b = new Test5(){{ value = 1 ;}};
Run Code Online (Sandbox Code Playgroud)

无法从静态上下文引用非静态变量.

双括号成语表明第二个括号是匿名类的实例初始值设定项.那么为什么不能初始化私有成员变量呢?

jan*_*nko 5

这条线

b = new Test5(){{ value = 1 ;}};
Run Code Online (Sandbox Code Playgroud)

创建一个扩展的匿名类的实例Test5.但是,因为value是私有的,匿名类无法访问其超类的实例变量.

由于value匿名子类中没有名为visible的变量Test5,因此编译器会在下一个范围中查找替代变量.在这种情况下,下一个范围属于静态main方法.编译器发现实例变量Test5,并发出警告,因为无法从静态上下文引用实例变量.

你有两个选择:

  1. 要使实例变量可以被匿名类访问: protected int value;

  2. 或者使变量可以被静态main方法访问: private static int value;

我从你的问题中得出结论,第一个选择是你真正想做的事情.

@Tom:问题在于首先搜索静态范围.如果是这种情况,则替代(1)将不起作用,因为value仍然首先找到实例变量,但仍然无法引用.

@Ken:你instanceMethod()不做,你期望它做什么!看看下面的代码:

class Test5A {
    private int value;

    public void instanceMethod() {
        Test5A a = new Test5A() {{ value = 1; }}; // (A)
        System.out.println(this.value);
        System.out.println(a.value);
    }

    public static void main(String[] args) {
        new Test5A().instanceMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

此示例代码模仿您的类的行为.如果编译并执行它,您将看到输出为"1 0".

虽然(A)中的匿名子类的实例初始化器看起来像是将一个子类分配给它自己的value实例变量,但该变量实际上只能在匿名类的超类中可见.取而代之的是,在该行(A)称为唯一可见的变量value是的实例变量Test5A在其上实例instanceMethod()被调用.因此,它变为一个.

现在让我们提高value:

class Test5B {
    protected int value;

    public void instanceMethod() {
        Test5B a = new Test5B() {{ value = 1; }};
        System.out.println(this.value);
        System.out.println(a.value);
    }

    public static void main(String[] args) {
        new Test5B().instanceMethod();
    }
}
Run Code Online (Sandbox Code Playgroud)

这次输出为"0 1".该实例变量value 由匿名子类继承,它它的实例初始化可见.因此,将一个分配给正确的实例变量.

  • 如果我将值设为"受保护"而不是"私有",那么Ajay的示例根本没有显示任何警告.即,问题是匿名类无法看到变量,而编译器假定从main的上下文访问非静态变量. (2认同)