java 编译中错误的意外顺序

Unexpected order of errors in java 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");
    }
}

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

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

import java.util.HashMap;

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

unreported exception IOException; must be caught or declared to be thrown

我的问题:

  1. 为什么在之前的编译尝试中没有抛出这个错误?
  2. 编译错误出现的顺序好像不太自然。在此例程中发挥作用的编译器设计原则是什么?

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

如果您 运行 javac-verbose,您会注意到编译器加载导入的 类,在本例中为 BufferedReaderInputStreamReader,然后加载 public API 类 像 ObjectString:

[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>();

通过查看 this link 中的概述,加载使用过的 类 本身是称为 "Parse and Enter":

的第一阶段编译的一部分

Each tree is passed to Enter, which enters symbols for all the definitions encountered into the symbols. This has to done before analysis of trees which might reference those symbols. The output from this phase is a To Do list, containing trees that need to be analyzed and have class files generated.