java前向引用在不同情况下的行为是否不同?

问题描述 投票:0回答:2

请看一下这个片段:

public class A {
    void method() {
        System.out.print(B.j);//This is legal!
        class C {
            void method () {
                System.out.print(j);//This is illegal!
            }
        }
        final int j = 10;
        class D {
            void method() {
                System.out.print(j);//This is legal!
            }
        }
    }
}
class B {
    static int j = 10;
}

我们可以在定义之前的某个地方访问“B.j”,但在访问类 C 中的“final int j”的情况下这是非法的。

java编译器是否将本地类视为简单的变量/对象?特别是,这种行为背后的理由是什么?我的意思是前向检查对 B.j 有效,但对 C 类中的“j”不起作用。

java inner-classes local-class
2个回答
5
投票

我相信这是简单的范围界定。如果您用简单的 System.out.println() 调用替换内部类,

public class A {
  void method() {
    System.out.print(j);//This is illegal!
    final int j = 10;
    System.out.print(j);//This is legal!
  }
}

您会发现收到相同的消息。局部变量的作用域从声明它们的地方开始,一直到声明它们的块的末尾。

回答你关于 B 参考的问题:考虑

public class A {
  void method() {
    System.out.print(k);//This is legal!
  }
  int k=17;
}

Java 不是单遍编译。类及其公开的字段和方法可以被前向引用。经过深思熟虑,局部变量不能被前向引用。我猜测这是为了让程序员建立受限制的范围,而不必使用额外级别的

{}
块语句 - 如果我引入一个新变量,尤其是初始化变量,我不希望任何人在此之前篡改它.

这就是 Java 局部变量的工作原理。这可能不是一个令人满意的答案,但这是我们得到的最好的答案。


0
投票

设置代码无法编译的可能性......

当类 A 被类加载器加载到内存中时,类 B 也被加载到内存中,因为它们位于同一个文件中。因此,当运行时调用

method
时,B.j 已经在堆上分配了。

另一方面,当您在方法中声明变量时,这些变量会在调用该方法时按照您编写它们的顺序存储在堆栈中,因此这里的顺序很重要。

© www.soinside.com 2019 - 2024. All rights reserved.