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

时间:2014-03-01 06:02:49

标签: java compiler-construction inner-classes local-class

请看一下这个片段:

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'。

2 个答案:

答案 0 :(得分: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局部变量恰好起作用的方式。这可能不是一个令人满意的答案,但它是我们得到的最好的答案。

答案 1 :(得分:0)

设置代码不会编译的可能性......

当类A由类加载器加载到内存中时,类B也是如此,因为它们在同一个文件中。因此,在运行时调用method时,已经在堆上分配了B.j.

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