認識下Java 中帶包(創建及引用)的類的編譯與調試

Java 源程序的編譯大家都知道,也就是 cmd 中到源文件所在目錄下 javac **.java 即可,當程序中有包聲明還能簡簡單單的直接 javac **.java 嗎?答案當然是 no。

下面舉個簡單的例子證明一下直接 javac **.java 會怎麼樣。

如下:F:\javaweb2班\20160531目錄下有A.java 文件,注意源文件中有包聲明:

實例

package mypack;
public class A {
    String name;
    int age;
    public void setName(String _name){
        this.name =_name;
    }
    public void setAge(int _age){
        this.age = _age;
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
    public static void main(String[] args){
        A a = new A();
        //a.setName("zs");
        a.name="zs";
        a.setAge(18);
        System.out.println(a.getName()+a.getAge());
    }
}

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

現在對 A.java 直接進行編譯 javac A.java 結果如下:

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

我們可以清楚地看到當前目錄下出現了A.class字節碼文件,就這樣能不能直接運行呢?試試吧!

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

出現了這樣的錯誤,原因是我們在 A.java 中有包聲明,當執行 A.java 源文件時 java 虛擬機首先會在 A.java 當前目錄尋找字節碼文件,雖然這下找到了,但是因爲在 A.java 中有包聲明,java 虛擬機緊接着去包目錄下尋找有沒有 A.class 字節碼文件,這下找到了才能夠成功執行,不信我們做做實驗!(這裏我再教教大家怎麼編譯有包聲明的 A.java,也就是打包編譯 javac -d . A.java 即可)

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

這下就打包編譯成功了,這時我們可以看到 mypack 目錄下出現了 A.class 文件,下面試試執行吧

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

這時我們發現執行還是不能通過??這時爲什麼呢?這裏是許多新手遇到的問題,在這裏大家必須謹記一點:Java 命令的參數是"類的完整類名",而不是"文件名"。

這個源程序的完整類名應該是 mypack.A,因此應該這麼寫:java mypack.A

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

這下就可以成功執行了!

別急!!下面還有更精彩的!作爲包的使用怎麼可能會不講解一下包的導入創建編譯呢!

這次我們引入另外一個測試類 Test.java,代碼如下:

實例

import mypack.A;
public class Test{
    public static void main(String[] args){
        A a = new A();
        a.setName("zs");
        //a.name="zs";
        a.setAge(18);
        System.out.println(a.getName()+a.getAge());
    }
}

編譯執行如下:

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

結果意料之中肯定是能夠編譯執行的,執行流程是這樣的:Test.java 編譯之後生成的字節碼文件在當前目錄(編譯時他會尋找 mypack 中是否有 A.class 文件,若無,編譯不通過),執行時,由於 Test.java 中沒有包聲明,java 虛擬機首先在當前目錄找到 Test.class 就會執行,執行到程序中引用到A類的地方,然後 java 虛擬機在當前目錄看是否有 A.class 字節碼文件,這時即使發現了也會根據源程序中的包導入進入包中尋找 A.class,找到才能執行成功(其實在編譯階段就已經尋找了!)

下面更進一步:若我們給測試類 Test.java 加上包聲明 package mypack1;

這時我們對 Test.java 進行打包編譯,這裏我又要給大家講解兩個知識點:1.打包編譯時,會自動創建包目錄,不需要自己新建包名文件夾;2.噹噹前目錄有多個java文件需要編譯或打包編譯時,javac -d . *.java 指令可以給當前目錄下的所有 java 文件根據程序中是否有包聲明進行編譯或打包編譯。

這時我們又該如何執行 Test.java 文件呢?java Test.java 嗎??顯然這樣是不行的,還記得我前面講過的麼:Java 命令的參數是"類的完整類名",而不是"文件名"。

因此我們需要這樣執行:

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

這樣就:

上面講的這些都是一般情況,也就是類路徑都是在當前目錄下,當類路徑不在當前目錄下是否還能執行呢?又該如果執行呢?

如下圖我把 Test.java 放到外面一層目錄,這時我們就需要自己設置 classpath 參數。例如:F:\javaweb2班>java -cp F:/javaweb2班/20160531 mypack1.java;或者在任意目錄下:java -cp F:/javaweb2班/20160531 mypack1.java

認識下Java 中帶包(創建及引用)的類的編譯與調試認識下Java 中帶包(創建及引用)的類的編譯與調試

這樣就成功了!具體的執行流程大家自己分析體會吧!

總結一下

  1. Java 命令的參數是"類的完整類名",而不是"文件名"。
  2. 打包編譯時,會自動創建包目錄,不需要自己新建包名文件夾。
  3. 當前目錄有多個 java 文件需要編譯或打包編譯時,javac -d . *.java 指令可以給當前目錄下的所有 java 文件根據程序中是否有包聲明進行編譯或打包編譯。
  4. 當類路徑不在當前目錄下時,需要用到 java -cp ...,如:java -cp F:/javaweb2班/20160531 mypack1.java。
  5. 要清楚 java 虛擬機根據包聲明包導入執行字節碼文件的流程。

本文地址:https://www.linuxprobe.com/understand-the-compilation.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章