2个java项目,cmd06将使用cmd07的类,2个项目的包空间是不同的
// cmd07被导入的类
package My;
public class Printer{
public void hello(){
System.out.println("hello");
}
}
// cmd06
package zhc;
import My.Printer;
class Main {
public static void main(String[] args){
Printer pp = new Printer();
pp.hello();
}
}
先编译的cmd07没问题,后编译cmd06时,应该会报错找不到类才对, javac src/zhc/Main.java -d . -verbose 用这个参数查看java命令的执行流程:
[解析开始时间 RegularFileObject[../src/zhc/Main.java]]
[源文件的搜索路径: .,/media/zhang/my150/jdk8/bin/zhc]
[类文件的搜索路径: /media/zhang/my150/jdk8/jre/lib/resources.jar,/media/zhang/my150/jdk8/jre/lib/rt.jar,(略)/media/zhang/my150/jdk8/jre/lib/ext/sunjce_provider.jar,.,/media/zhang/my150/jdk8/bin/zhc]
../src/zhc/Main.java:3: 错误: 程序包My不存在
源文件搜索路径:对应的是命令行参数-sourcepath,查找后缀名.java的目录。我没有指定该参数,惊讶地发现其值和我的环境变量CLASSPATH一样。
类文件搜索路径:对应的不只是命令行参数-classpath,查找java源文件中涉及到的类,即后缀.class文件的目录。我没有指定该参数,其值由3部分组成:jre/lib目录,可以通过System.getProperties("sun.boot.class.path")查看 , 第二部分是jre/lib/ext目录,可以通过System.getProperties("java.ext.dirs")查看, 最后才是环境变量CLASSPATH指定的路径。如果要查找的类在CLASSPATH中有,在jre/lib/ext目录也有一份不同的版本,则会优先使用ext中的版本。
我这里把cmd07类的根目录,或者cmd07.jar , 设置为CLASSPATH,就可以编译成功了。javac src/zhc/Main.java -d . -classpath cmd07/target -verbose
[解析开始时间 RegularFileObject[../src/zhc/Main.java]]
[解析已完成, 用时 22 毫秒]
[源文件的搜索路径: /media/zhang/my150/proj/cmd07/target]
[类文件的搜索路径: /media/zhang/my150/jdk8/jre/lib/resources.jar,(略)/media/zhang/my150/jdk8/jre/lib/ext/jaccess.jar,/media/zhang/my150/jdk8/jre/lib/ext/sunjce_provider.jar,/media/zhang/my150/proj/cmd07/target]
[正在加载RegularFileObject[/media/zhang/my150/proj/cmd07/target/My/Printer.class]]
[正在加载ZipFileIndexFileObject[/media/zhang/my150/jdk8/lib/ct.sym(META-INF/sym/rt.jar/java/lang/Object.class)]]
[正在加载ZipFileIndexFileObject[/media/zhang/my150/jdk8/lib/ct.sym(META-INF/sym/rt.jar/java/lang/String.class)]]
[正在检查zhc.Main]
可见,javac命令流程是先分析入口源代码,然后列出所有的查找范围,然后查找入口源码所需的外部类,找不到就报错,找到就加载.class文件到JVM内存中生成类对象,后面在需要的时候,比如Printer pp = new Printer(); 再实例化
原文:https://blog.51cto.com/u_6132776/3288041