Java:windows shell 下package和import的問題:類放在同一包下為什麼顯示cant find symbol?
使用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,即使是“同名的包”