使用cmd或者powershell运行java注意事项
不使用IDE时,我们编写多个java文件后想要编译并测试运行的话,需要注意一些问题
对于运行入口的App.java或者测试XXTest.java而言,需要cmd在根package目录的上一级目录下运行
比如你要写一个软件,myapp,创建了根目录myapp,编写的所有类文件都在myapp内
软件入口App.java位于 myworkspace\myapp\App.java
在保证myapp下所有类的import和package以myapp为根命名时
编译此文件,cmd的访问位置必须是:myworkspace > javac myapp/App.java
cmd访问方式产生的问题
如果在App.java当前或者其他目录按相对路径访问java文件,比如
myworkspace\myapp> javac App.java
F:> javac myworkspace\myapp\App.java
问题:
如果App.java有非同文件下的依赖类:
编译器报cant find symbol 错误
原因:
是cmd下编译java文件,当前类需要某个外部依赖类字节码时,
1. 写了package没写import
编译器读取package标识,按照其路径,在cmd位置,向下扫描依赖类
1-1. 如果找到依赖类,访问class文件,读取package标识,标识为同包即找到该依赖类 OK!
1-2. 如果找到依赖类,访问class文件,读取package标识,标识为不同包即未找到
如果2)始终找不到package标识相同的依赖类class文件,显示错误,cant find symbol,bad class file
2. 写了import,或标识了类前缀
如果1中过程没找到依赖类,编译器就读取import标识和前缀,按照其路径,在cmd位置,向下扫描依赖类,
后面具体过程和1-1和 1-2相同
显然,按照java规范,cmd如果不在根package上一级目录,运行编译,那么肯定找不到依赖类(import配置过环境变量的java classpath除外),相反就是package与import命名不规范。
举个不同包(2个类package命名不同,或不在一个物理地址目录下)的例子
情景:
假设我们有2个java文件 App.java(未编译) Dependency.java(已编译),App继承Dependency,或调用其静态字段和方法
设package根目录为\app 物理地址c: \home\app
Dependency目录: \app\dependency
即Dependency.java注明 package app.dependency;
App目录: \app
即App.java注明 package app; import app.dependency.Dependency;
此时假设cmd在\app运行
c:\home\app > javac App.java
显示错误: cant find symbol;描述原因:package app.app.dependency不存在;按照import app.dependency.*找不到Dependency.class;
过程描述:编译器读取了App.java,先按照App所在包package app;
;以c:\home\app
为当前位置,向下查找\app
文件夹看是否有Dependency.class
,发现c:\home\app\app
不存在。
然后启动import,按照import app.dependency.Dependency;
,查找c:\home\app\app\dependency\Dependency.class
,发现不存在
解决方法:cmd在package根目录上一级运行编译即可。
注意这里有个trick,类的package命名同包,但是物理地址不在一个目录下,虽然实际上类不同包,但可以不用import访问依赖类,如下:
设package根目录为\app 物理地址c: \home\app
Dependency目录: \app\dependency
Dependency.java注明 package app.dependency;
违反规范!
App目录: \app
即App.java注明 package app.dependency;
此时假设cmd在app上一级目录运行javac编译App.java,
App可以访问Dependency的公开字段和方法,且不用写import
但是对于保护字段和方法就不行,系统会显示Exception in main thread trying to access protected field,即使是“同名的包”