java - Java编译中错误的意外顺序

标签 java compilation compiler-errors

在解决在线挑战时,我观察到 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");
    }
}

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

  • 我没有处理可能由 BufferedReader 抛出的异常。
  • 我没有导入包含 HashMap 的标准 util 库。

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

import java.util.HashMap;

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

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

我的问题:

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

最佳答案

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

如果您使用 -verbose 运行 javac,您会注意到编译器加载导入的类,在本例中为 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 中的概述,加载使用的类本身是称为“解析和输入”的第一阶段编译的一部分:

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.

关于java - Java编译中错误的意外顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31122606/

相关文章:

C#条件运算符错误只有assignment,call,increment,decrement,await,new object expressions可以作为语句使用

java - Hibernate/JPA可选的一对一双向映射

java - 忽略字符串中的数字

c++ - 在同一项目中混合使用 C++ 风格

c++ - 将 CGAL 与 Code::Blocks 结合使用

c++ - 为什么GCC会说 “a function-definition is not allowed here before ' {' token”?

java - Java 中的事件(监听器)

java - 在 SimpleXML 注释中指定集合类型

c++ - 在多个共享库中静态库成员的多重初始化

xcode - c++ 函数式/std::bind 不能用 Apple Clang 编译