在静态方法中实例化的匿名内部类是否可以访问包含类的实例成员?



我想更好地了解包含类的实例字段对匿名内部类(AIC)的可见性。

有很多讨论说 AIC 隐式引用了包含类的实例(使用(匿名)内部类究竟什么时候泄漏安全?使用该逻辑,即使在静态方法中实例化 AIC,它也应该有权访问包含类的实例字段。但是我找不到一种方法来测试这一点,因为编译器会给出错误。

例如,在下面的代码中,当我在 AIC 的 print() 方法中引用"s"时,编译器会得到:"非静态字段 's' 不能从静态上下文中引用">

public interface TestInterface {
void print();
}

public class AICTest {
public String s = "something";
public static void main( String[] args ) {
new TestInterface() {
@Override
public void print() {
System.out.println( s ); **<-- compilation error**
}
}.print();
}
}

您能否建议 AIC 实例是否可以访问上述示例中的"s"?

编辑/回答我想澄清一下,我知道静态方法可以访问类成员,实例方法可以访问实例和类成员。混淆更多的是关于AIC总是隐含地引用包含类对象的一般性陈述。对于在静态方法中初始化的 AIC,情况显然并非如此。@shmosel分享了一个链接来回答我的问题(是否可以在Java中使匿名内部类成为静态的?):"因此,静态上下文中的匿名类大致等同于静态嵌套类,因为它不保留对封闭类的引用,即使它在技术上不是静态类。

您必须有一个 AICTest 的实例才能从中读取 's',因为 's' 是一个实例变量。 下面是一个可行的示例,表示修改后的示例,以访问可能来自任何位置的现有 AICTest 对象:

class AICTest {
public String s = "something";
public static void main( String[] args ) {
AICTest aic = new AICTest();
new TestInterface() {
@Override
public void print() {
System.out.println(aic.s);
}
}.print();
}
}

需要明确的是,运行"main"不会创建 AICTest 的实例。 您必须在某处执行"新建"操作才能创建 AICTest 的实例。

另一种选择是将"s"设为静态。 然后,它不与任何特定的 AICTest 对象关联,因此即使您尚未实例化 AICTest 对象,它也存在:

class AICTest {
public static String s = "something";
public static void main( String[] args ) {
new TestInterface() {
@Override
public void print() {
System.out.println(s);
}
}.print();
}
}

如您所见,我没有添加任何可见性修饰符。 所以你关于可见性的想法是合理的。 如果访问"s"有意义,则可见性存在于您的代码中。 这里的问题与可见性无关。

这可能不是您想要的,但您可以:

interface TestInterface {
void print();
}
class AICTest {
public String s="something";
public static void main(String[] args) {
AICTest aicTest=new AICTest();
new TestInterface() {
@Override public void print() {
System.out.println(aicTest.s);
}
}.print();
}
}

混淆更多的是关于一般哲学,即AIC总是隐含地引用包含类的对象。对于在静态方法中初始化的 AIC,情况显然并非如此。@shmosel分享了一个链接来回答我的问题(是否可以在Java中使匿名内部类成为静态的?):"因此,静态上下文中的匿名类大致等同于静态嵌套类,因为它不保留对封闭类的引用,即使它在技术上不是静态类。

最新更新