java编译中出现意外的错误顺序

Bho*_*oot 7 java compiler-errors compilation

在线解决挑战时,我发现了java的以下行为,我发现它有点奇怪.我从以下大纲编写程序开始:

import java.io.*;

class WeirdJava
{
    public static void main (String[] args) 
    {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String input = br.readLine();
        HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
        System.out.println("Weird Java");
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,在上面的程序中,有两个错误:

  • 我没有处理可能引发的异常BufferedReader.
  • 我没有导入util包含的标准库HashMap.

现在,当我尝试编译上面的程序时,java编译器给出了它无法找到符号的错误HashMap.请注意,涉及的声明HashMap是在之后BufferedReader.接下来,我将以下import语句添加到程序中:

import java.util.HashMap;
Run Code Online (Sandbox Code Playgroud)

当我再次编译程序时,这次编译器显示错误

未报告的异常IOException; 必须被抓住或宣布被抛出

我的问题:

  1. 为什么在先前的编译尝试中没有抛出此错误?
  2. 编译错误的顺序似乎并不自然.在此例程中,编译器设计原则是什么?

man*_*uti 4

这只是编译器检查源代码的顺序。特别是,编译器会在检查调用可能引发已检查异常的方法的代码之前检查导入并解析它们。

如果您运行javacwith -verbose,您会注意到编译器加载导入的类,在本例中为BufferedReader和InputStreamReader,然后加载公共 API 类,例如Object和String:

[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/io/BufferedReader.class)]]
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/io/InputStreamReader.class)]
]    
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Object.class)]]
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/lang/String.class)]]
[checking test.Test]
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/lang/AutoCloseable.class)]]
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/lang/System.class)]]
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/io/InputStream.class)]]
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/io/Reader.class)]]
Test.java:11: error: cannot find symbol
    HashMap<Integer, Integer> map = new HashMap<Integer,Integer>();
Run Code Online (Sandbox Code Playgroud)

通过查看此链接中的概述,加载使用的类本身是称为“解析和输入”的第一阶段编译的一部分:

每棵树都会传递给 Enter,它将遇到的所有定义的符号输入到符号中。这必须在分析可能引用这些符号的树之前完成。此阶段的输出是一个待办事项列表,其中包含需要分析并生成类文件的树。