同包下互相引用的两个Java文件编译运行异常问题问询
问题1:编译报错的原因
Java引入包机制后,类的全限定名是包名.类名,编译器查找依赖类时,会按照全限定名对应的目录结构去搜索源文件/类文件:
- 你给两个类都加了
package myPack后,Test类的全限定名是myPack.Test - 当你在
myPack目录下执行javac Main.java时,编译器默认的类搜索根路径是当前目录(也就是myPack文件夹本身),要找myPack.Test就需要当前目录下存在myPack/Test.java的路径,可你的Test.java直接放在当前myPack目录下,没有嵌套的子myPack文件夹,编译器找不到对应的Test类定义,就会报找不到符号的错误。 - 手动指定
javac Main.java Test.java相当于直接告诉编译器把两个源文件都纳入本次编译,编译器不需要再自行搜索Test的源文件,所以可以编译通过。
问题2:运行时报找不到主类的原因
这个错误是主类的全限定名不匹配导致的:
- 加了包声明后,Main类的全限定名是
myPack.Main,不是无包的Main - 执行
java Main时,JVM只会在默认类路径(当前myPack目录)下搜索没有包的名为Main的主类,自然找不到带包的myPack.Main类。 - 哪怕你在
myPack目录下执行java myPack.Main也会报错,因为JVM会去当前目录下找myPack/Main.class,也就是myPack/myPack/Main.class的路径,这个路径不存在。
问题3:父目录编译运行可以成功的原因
本质是符合了Java包机制要求的「类路径+全限定名」匹配规则:
- 从父目录执行
javac myPack/Main.java时,编译器的默认类搜索根路径是父目录(也就是包含myPack文件夹的目录),要找依赖的myPack.Test时,直接就能匹配到父目录下的myPack/Test.java文件,会自动把Test也加入编译,不需要你手动指定。 - 执行
java myPack.Main时,JVM的默认类路径是当前父目录,会按照全限定名去父目录下找myPack/Main.class,刚好匹配编译生成的类文件路径,所以可以正常加载主类运行。 - 带包的Java程序编译运行的核心规则就是:要把包结构的根目录(也就是包名对应文件夹的父目录)加入类路径,用全限定名指定要编译运行的类。
内容的提问来源于stack exchange,提问作者AmirCH
相关产品推荐
相关产品推荐

