1. 程式人生 > >Java中的package和import 感性認識

Java中的package和import 感性認識

為什麼要使用package和import

現在我學習Java遇到了class類的複用的問題,比如我昨天寫了一個Person類,它和包含main()方法的類放在一個java檔案中。類似如下

public class MainClass{
	public static void main(String[] args){
		Person jack = new Person("Jack",18);
		jack.sayHello();
	}
}

class Person{
	private String name;
	private int age;
	public Person(String _name,int _age){
		name=_name;
		age=_age;
	}
	
	public void sayHello(){
		System.out.println("Hi! I'm "+name+" and "+age+" years old");
	}
}

結果今天我寫新的程式設計練習,又想使用這個Person類,我似乎需要把這個類的程式碼複製到我新的Java檔案中。這可不是辦法啊,另外我還發現當我在一個java原始檔中寫了兩個類時,編譯出來的class檔案會有兩個,例如上面的程式碼編譯後,會有MainClass.class和Person.class。

所以是不是利用“import Person;”程式碼,就能在我新寫的程式碼中直接使用Person類呢?事情似乎沒這麼簡單。首先我的Person.class檔案,來自於對上面程式碼的編譯,但是這個類不是一個public類(一個java檔案中只能有一個public類,並以此類作為java檔案的檔名)。所以沒有辦法使用當前的Person.class檔案。

所以我要為Person.class重寫一個獨立的java檔案,將Person類改為public型別。當我寫的類越來越多時,就要使用package關鍵字給他們打包。打包,字面意義而已。

package打包

當我在Person類原始檔中加上

package madokast;

這段語句後。再利用javac -d . Person.java編譯,class檔案就不會出現在當前資料夾中,而是當前資料夾中新出現了一個叫madokast的新資料夾,開啟后里面才有Person.class檔案。
為了更好的管理原始檔Java和編譯後的class檔案,我們一般建立一個專案project資料夾,然後在裡面建立原始檔 source/src

資料夾和類classes資料夾,這樣一來,讓原始檔和編譯好的類檔案分家,整個專案清晰美觀。
project
|++source
|—++madokast
|———Person.java
|——MainClass.java
|++classes
|—++madokast
|———Person.class
|——MainClass.class

這樣在MainClass.java中新增語句,也能進一步的展示專案的檔案結構。

import madokast.Person;

記得編譯和執行語句分別是(當前目錄處於project資料夾下)

javac -d ./classes ./source/madokast/Person.java
javac -d ./classes -classpath ./classes ./source/MainClass.java
java -classpath ./classes MainClass

javac編譯MainClass.java時,需要讓編譯器javac知道madokast.Person類所在的位置,不然會報錯說無法識別Person符號。
java執行語句時,也需要指出類的位置。

這裡有個細節我到今天才清楚,那就是java執行的是MainClass命令,而不是MainClass.class檔案,因為如果你寫成以下幾種形式,都無法執行
java -classpath ./classes ./classes/MainClass
java -classpath ./classes MainClass.class
java -classpath ./classes ./classes/MainClass.class
也許java的執行是這樣的——當它得知需要執行MainClass命令時,就去我設定的環境變數、classpath地址、當前地址中搜索MainClass.class檔案,當以上路徑都找不到這個檔案時,就自然報錯。

可以不用import語句

每個類都有獨一無二的名字,那就是packageName.ClassName,因此使用 madokast.Person 就能讓編譯器知道其位置。

最後說下感受。今天學到Java的package管理,突然覺得這種模式比C/CPP好多了,C/CPP中分標頭檔案和原始檔,而我最近在書上看到說,根本沒必要用標頭檔案,多此一舉,因為標頭檔案主要就是所謂的宣告,原始檔是具體的函式定義,實際上編譯器完全可以把函式定義當作宣告去尋找,沒有必要使用函式前,先有其宣告語句。
的確呀。我在最上面貼的Java程式碼中,沒看到MainClass類上面還寫一句

class Person;

直接使用Person類,毫無問題。

另外一點是,Java中所有東西強制在類裡面,這樣編譯後,一個class檔案就是一個完整的類,實乃順水行舟的存在。所以在一個java原始檔中,最好是隻定義一個類,有多少個類,就寫多少個java原始檔,這樣source資料夾和classes資料夾裡的內容就像一面鏡子,太漂亮了。
當然你要按照package的語句把Java檔案放在對應的資料夾中。這樣子的雙重操作,一面有點繁瑣,一面又提醒我package命名的統一。

(注:此人還沒有安裝Java IDE,打算再研究一兩週的時間)
(這時寫的第一篇文章。可惜現在很忙,一面要學習geant4,bdsim軟體,一面正在偷偷學Java,計算機組成和資料結構。大概寫文章最主要的目的就是整理自己的思路,而不是簡單地羅列學到的知識點,所以稱為感性認識)