考虑我在java编译单元中使用来自包foo.bar
的类型X
,并且X
不是在编译单元本身中定义的,也不是直接导入的。如何一个java编译器解决X
现在有效?X
可能存在以下几种情况:
-
X
可以通过星形导入a.b.*
导入 -
X
可能与编译单元 位于同一个包中。 -
X
可能是一种语言类型,即驻留在java.lang
我看到的问题是特别(2)。由于X
可能是包私有类型,因此甚至不要求X
驻留在名为X.java
的编译单元中。因此,编译器必须查看类路径的所有条目,并搜索包foo.bar
中的任何类,然后必须读取包foo.bar
中的每个类,以检查是否包含X
。
听起来很贵。特别是当我只编译一个文件时,编译器必须读取几十个类文件才能找到一个类型X
。如果我使用了大量的星型导入,那么这个过程就必须对许多类型重复执行(当然,类文件不会被读取两次)。
那么从同一个包中导入also类型以加快编译过程是否可取呢?或者是否有更快的方法来解决我无法找到的未导入类型X
?
听起来很贵。
如果编译器这样做,它将是昂贵的。
但实际发生的是,它构建了一个内存中的数据结构,其中包含类路径,bootclasspath和sourcepath上的所有类名,并将其用于javac
运行中编译的所有类中的所有类名解析。
那么从同一个包中导入also类型以加快编译过程是否可取呢?或者是否有更快的方法来解决我无法找到的未导入类型X ?
No, and No。这几乎没有什么区别。此外,如果您按照设计的方式使用编译器,那么这不大可能成为一个重大的瓶颈。
因此,编译器必须查看类路径的所有条目,并在包foo.bar
中搜索任何类。
这就是Class.forName()
。
则必须读取包foo中的所有类。栏检查是否包含X。
我不知道这是什么意思
通过Class.forName(),
查找.class文件后,它必须在当前包的源路径中查找文件的适当名称,即new File(...).exists()
等。
我不相信它会在每个文件中查找该名称的非公共类:您必须尝试它。如果是这样,这确实是一个昂贵的步骤,但我不相信它已经采取了