在Java中声明类时顺序重要吗?

在Java中声明类时顺序重要吗?,java,Java,为什么这段代码甚至不编译 public class T { public static void main(String[] args) { class A extends B {} class B {} B a = new A(); } } 错误: Error:(10, 25) java: cannot find symbol symbol: class B location: class com.test.T Er

为什么这段代码甚至不编译

public class T {
    public static void main(String[] args) {
        class A extends B {}
        class B {}
        B a = new A();
    }
}
错误:

Error:(10, 25) java: cannot find symbol
  symbol:   class B
  location: class com.test.T
Error:(12, 15) java: incompatible types
  required: B
  found:    A
在声明此类类时,顺序真的很重要吗?

是的,它对本地类很重要。值得注意的是,本地类在实际代码中极其罕见。我只记得用过一次。然而,为了利益

联合联络小组:

直接由块(§14.2)封闭的局部类声明的范围是直接封闭块的其余部分,包括其自身的类声明

现在“rest”不是很清楚,但我相信它的意思是“从这一点开始”。因此基本上
B
不在
A
声明的范围内,因此出现了错误

为了增加乐趣,在声明
B
之前,您可以参考另一种称为
B
的类型:

public class T {

    public static void main(String[] args) {
        class A extends B {}
        class B {}
        B a = new A();
    }
}

class B {}
给出:

错误:不兼容的类型:无法将A转换为B

更改此项:

公共T类{

public static void main(String[] args) {

    B b = new A();
}
}

B类{ }

A类延伸至B类{
}

对于顶级课程,否

对于本地课程,是的,但请参见John Skeet的答案:

与C#和大多数其他现代编译器一样,Java首先解析整个文件以及同一范围内的其他文件或导入,用它看到的顶级类型符号填充编译器符号表(在此步骤中不进一步解析这些类型的内部),然后在后面的步骤中,编译器解析符号引用;一旦收集了所有符号,它们就没有词汇顺序或优先级,就好像它们都同时在同一行上声明一样。这就是它实现以下概念的方式(来自JLS-)

一个声明被认为是在一个特定的时间点的范围内 当且仅当声明的作用域包含该点时编程

可观测(§7.4.3)顶层声明的范围 包是所有可观察的编译单元(§7.3)

顶级类型(§7.6)的范围是 在其中声明顶级类型的包

除其他外

这就是为什么在Java/C#中创建循环关系很简单,而在旧语言(如C/C++中,编译器只向后看)中不需要前向声明,因此前向声明是真正向前的东西的虚拟或占位符

但是,在Java方法体中,Java使用词法顺序,并将具有相同顺序规则的类视为局部变量。(见约翰·斯凯特的回答:)


我可以想出几个理由来解释为什么要这样做是为了保持理智,但归根结底是由编译器/语言设计者做出的决定。我的意见是,这只是为了一致性。否则,我们会对本地事物有两种不同的规则,这类事情会让人困惑。如果你曾经做过很多Perl编程,你就会知道维护一个特殊情况和上下文特定规则的心理缓存是多么困难。

是的,我试过这个。但问题是关于方法范围内的类顺序。虽然这可能回答OP的问题,但几句解释将有助于当前和未来的读者更好地理解它。