第一個是path 和 CLASSPATH的問題
第二個是package和import問題
第三個是public,protected,private,static,什麼時候用,為什麼要用,怎麼用
第四個是製作jar檔案
第一個,path 和 CLASSPATH的問題
什麼是path
是你的JDK的工作路徑
例如 你的jdk安裝在C:/jdk/ 此時的你的path(如果原來沒有PATH)設定為 PATH ;C:/jdk/ bin
什麼是Classpath
Classpath是Java中的重要概念,它描述了Java虛擬機器在運行一個Class時在哪些路徑中載入要啟動並執行類以及啟動並執行類要用到的類。簡單的說,當一個程式找不到他所需的其他類檔案時,系統會自動到CLASSPATH環境變數所指明的路徑中去尋找第三方提供的類和使用者定義的類,
Classpath和Java包的關係
Java的包(Package)和classpath關係密切。包是以“.”分割的,SUN建議使用網域名稱的逆向排列來區分不同的包,以避免衝突,如com.company.util。在一個包裡的類在儲存的時候需要儲存在和包名相同的目錄裡,如上述com.company.util包中的Sample.class,要儲存在com/company/util目錄中。
Classpath有兩種表達方式,一種是指向目錄的classpath,如C:/work/classes,表示C:/work/classes目錄是一個classpath條目;另一種方式是指向壓縮檔的classpath,如C:/work/util.jar,表示C:/work/util.jar檔案是一個classpath條目,任何一個包含Java類的zip格式的壓縮檔都可以作為classpath的條目。
那麼classpath和包到底是什麼關係呢?簡單的說,就是Java虛擬機器在載入類的時候以這樣一種方式尋找具體的類檔案:classpath+包儲存的目錄+具體的類檔案。如classpath中有一個c:/work/classes條目,需要載入的類是com.company.util.Sample.class,那麼在載入這個類的時候,虛擬機器會尋找c:/work/classes/com/company/util目錄,如果Sample.class在這個目錄中,虛擬機器就可以找到,如果這個類不在這個目錄中,同時也不在任何一個其它classpath中,那麼虛擬機器會拋出一個ClassNotFoundException。
Classpath的順序和類版本衝突
Java虛擬機器在載入類的時候尋找classpath是有順序的,如果在classpath中有多個條目都有同一個名稱的類,那麼在較前位置的類會被載入,後面的會被忽略。這種按照順序的類載入可能會導致類的版本衝突。例如classpath=c:/servlet2.2/servlet.jar;c:/servlet2.3/servlet.jar,那麼在實際應用的過程中,你使用的是servlet2.2,而不是servlet2.3。很多時候如果不注意這一點,可能會導致奇怪的異常。
命令列狀態下的classpath設定
命令列狀態下的classpath可以通過兩種方式設定。
一種是直接設定環境變數,例如在windows環境下,我們使用set命令:
set classpath=c:/work/classes;c:/work/util.jar
另一種方式是在執行javac、java或者其它Java命令時直接指定classpath:
java -classpath c:/work/classes;c:/work/util.jar com.company.util.Sample
二 package和import問題
Java中的包(Package)其實指的就是目錄,它是為了更好地管理Java類(Class)和介面(Interface)。Java語言的包可以被另一個Java開發包所使用。如果我們要引用某個包中的類,用import關鍵字來標明即可,Package行要在 import 行之前 ,Package打包後將產生在Classpath 指明的路徑下
例如 Classpath 為 C:/test
Package com.dir
結果為 將在C:/test目錄下產生com子目錄,目錄com包含dir目錄 所有的檔案將放在dir目錄
在Java中對象的體現在包的定義和應用中,對於已經編好的類,如果在新類中要使用,應將已經定義的類包含近來,Java中用import語句實現.
使用import 語句的加入所有類(以上面Package打包為例)
import com.dir.*;
使用import 語句的加入特指類(以上面Package打包為例,假如目錄中存在hello.class)
import com.dir.hello;
第三,public,protected,private,static,什 麼時候用,為什麼要用,怎麼用
每個類都創造了有自己的名字空間,指方法和變數可以知道彼此的存在,可以使用。
public類不但可以被同一程式包中的其它類使用,別的程式包中的類也可以使用;
變數和方法的修飾字public、protected、private:
public:任何其他類、對象只要可以看到這個類的話,那麼它就可以存取變數的資料,或使用方法。
class ABC{
public int pub_i=5;
public void show)(){
System.out.println("pub_i"+pub_i);
}
class Demo{
public static void main(String args[]){
ABC abc=new ABC();
System.out.println("abc.pub_i"+abc.pub_i);
abc.pub_i=10;
abc.show();
}
}
protected變數和方法:
如果一個類中變數或方法有修飾字protected,同一類、同一包可以使用。不同包的類要使用,必須是該類的子類,可以存取變數或調用。
public class ABC{
protected int pro_i=5;
protected void show(){
System.out.println("pro_i=" +pro_i);}
}
同包的類:
class DEF{
public static void main(String args[]){
ABC abc=new ABC();
System.out.println("abc.pro_i="+abc.pro_i);
abc.pub_i=10;
abc.show();
}
}
不同包但是是子類:
import mytest.pack.ABC;
class DEF extends ABC{
public static void main(String agrs[]){
DEF def=new DEF();
System.out.println(def.i);
def.i=10;
def.show();}
}
private不允許任何其他類存取和調用;
當子類中的變數名與父類的相同,原來的變數被遮蓋。
方法的覆蓋(overriding)和重載(overloading)。子孫類中定義的方法和祖先類中某個方法同名、同參數行,則祖先類中的該方法被覆蓋;方法的重載是指一個對象的多態性,即多個方法用相同的名稱,但參數行不同。
final:
final在方法之前,防止該方法被覆蓋;
final在類之前,標是該類不能被繼承;
final在變數之前,定義一個常量。
static:
在變數或方法之前,表明它們是屬於類的;
靜態變數在各執行個體間共用,如果是public靜態變數,則其它類可以不通過執行個體化訪問它們;
靜態方法稱為類的方法,因此不用執行個體化即可調用(面向過程)
一個對象的方法可以訪問對象的資料成員,儘管不屬於方法的局部變數;一個類的方法只能訪問自己的局部變數。
例:不正確的引用
class StaticError{
String mystring="hello";
public static void main(String args[]){
System.out.println(mystring);}
}
錯誤資訊:can’t make a static reference to nonstatic variable.
為什麼不正確?只有對象的方法可以訪問對象的變數。
解決的辦法:
1) 將變數改稱類變數
class StaticError{
static String mystring="hello";
public static void main(String args[]){
System.out.println(mystring);}
}
2) 先建立一個類的執行個體
class NoStaticError{
public static void main(String args[]){
String mystring="hello";
System.out.println(mystring);}
}
}
第四個,製作jar檔案
JAR 檔案就是 Java Archive File,顧名思意,它的應用是與 Java 息息相關的,是 Java 的一種文檔格式。JAR 檔案非常類似 ZIP 檔案——準確的說,它就是 ZIP 檔案,所以叫它檔案包。JAR 檔案與 ZIP 檔案唯一的區別就是在 JAR 檔案的內容中,包含了一個 META-INF/MANIFEST.MF 檔案,這個檔案是在產生 JAR 檔案的時候自動建立的
jar 命令詳解
jar 是隨 JDK 安裝的,在 JDK 安裝目錄下的 bin 目錄中,Windows 下檔案名稱為 jar.exe,Linux 下檔案名稱為 jar。它的運行需要用到 JDK 安裝目錄下 lib 目錄中的 tools.jar 檔案。不過我們除了安裝 JDK 什麼也不需要做,因為 SUN 已經幫我們做好了。我們甚至不需要將 tools.jar 放到 CLASSPATH 中。
使用不帶任何的 jar 命令我們可以看到 jar 命令的用法如下:
jar {ctxu}[vfm0M] [jar-檔案] [manifest-檔案] [-C 目錄] 檔案名稱 ...
其中 {ctxu} 是 jar 命令的子命令,每次 jar 命令只能包含 ctxu 中的一個,它們分別表示:
-c 建立新的 JAR 檔案包
-t 列出 JAR 檔案包的內容列表
-x 展開 JAR 檔案包的指定檔案或者所有檔案
-u 更新已存在的 JAR 檔案包 (添加檔案到 JAR 檔案包中)
[vfm0M] 中的選項可以任選,也可以不選,它們是 jar 命令的選項參數
-v 產生詳細報告並列印到標準輸出
-f 指定 JAR 檔案名稱,通常這個參數是必須的
-m 指定需要包含的 MANIFEST 資訊清單檔
-0 只儲存,不壓縮,這樣產生的 JAR 檔案包會比不用該參數產生的體積大,但速度更快
-M 不產生所有項的清單(MANIFEST〕檔案,此參數會忽略 -m 參數
[jar-檔案] 即需要產生、查看、更新或者解開的 JAR 檔案包,它是 -f 參數的附屬參數
[manifest-檔案] 即 MANIFEST 資訊清單檔,它是 -m 參數的附屬參數
[-C 目錄] 表示轉到指定目錄下去執行這個 jar 命令的操作。它相當於先使用 cd 命令轉該目錄下再執行不帶 -C 參數的 jar 命令,它只能在建立和更新 JAR 檔案包的時候可用。
檔案名稱 ... 指定一個檔案/目錄列表,這些檔案/目錄就是要添加到 JAR 檔案包中的檔案/目錄。如果指定了目錄,那麼 jar 命令打包的時候會自動把該目錄中的所有檔案和子目錄打入包中。
下面舉一些例子來說明 jar 命令的用法:
1) jar cf test.jar test
該命令沒有執行過程的顯示,執行結果是在目前的目錄產生了 test.jar 檔案。如果目前的目錄已經存在 test.jar,那麼該檔案將被覆蓋。
2) jar cvf test.jar test
該命令與上例中的結果相同,但是由於 v 參數的作用,顯示出了打包過程,如下:
標明清單(manifest)
增加:test/(讀入= 0) (寫出= 0)(儲存了 0%)
增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%)
3) jar cvfM test.jar test
該命令與 2) 結果類似,但在產生的 test.jar 中沒有包含 META-INF/MANIFEST 檔案,打包過程的資訊也略有差別:
增加:test/(讀入= 0) (寫出= 0)(儲存了 0%)
增加:test/Test.class(讀入= 7) (寫出= 6)(壓縮了 14%)
4) jar cvfm test.jar manifest.mf test
運行結果與 2) 相似,顯示資訊也相同,只是產生 JAR 包中的 META-INF/MANIFEST 內容不同,是包含了 manifest.mf 的內容
5) jar tf test.jar
在 test.jar 已經存在的情況下,可以查看 test.jar 中的內容,如對於 2) 和 3) 產生的 test.jar 分別應該此命令,結果如下;
對於 2)
META-INF/
META-INF/MANIFEST.MF
test/
test/Test.class
對於 3)
test/
test/Test.class
6) jar tvf test.jar
除顯示 5) 中顯示的內容外,還包括包內檔案的詳細資料,如:
0 Wed Jun 19 15:39:06 GMT 2002 META-INF/
86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF
0 Wed Jun 19 15:33:04 GMT 2002 test/
7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class
7) jar xf test.jar
解開 test.jar 到目前的目錄,不顯示任何資訊,對於 2) 產生的 test.jar,解開後的目錄結構如下:
==
|-- META-INF
| `-- MANIFEST
`-- test
`--Test.class
8) jar xvf test.jar
運行結果與 7) 相同,對於解壓過程有詳細資料顯示,如:
建立:META-INF/
展開:META-INF/MANIFEST.MF
建立:test/
展開:test/Test.class
9) jar uf test.jar manifest.mf
在 test.jar 中添加了檔案 manifest.mf,此使用 jar tf 來查看 test.jar 可以發現 test.jar 中比原來多了一個 manifest。這裡順便提一下,如果使用 -m 參數並指定 manifest.mf 檔案,那麼 manifest.mf 是作為資訊清單檔 MANIFEST 來使用的,它的內容會被添加到 MANIFEST 中;但是,如果作為一般檔案添加到 JAR 檔案包中,它跟一般檔案無異。
10) jar uvf test.jar manifest.mf
與 9) 結果相同,同時有詳細資料顯示,如:
增加:manifest.mf(讀入= 17) (寫出= 19)(壓縮了 -11%)
關於 JAR 檔案包的一些技巧
1) 使用 unzip 來解壓 JAR 檔案
在介紹 JAR 檔案的時候就已經說過了,JAR 檔案實際上就是 ZIP 檔案,所以可以使用常見的一些解壓 ZIP 檔案的工具來解壓 JAR 檔案,如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等來解壓是因為它們解壓比較直觀,方便。而使用 unzip,則是因為它解壓時可以使用 -d 參數指定目標目錄。
在解壓一個 JAR 檔案的時候是不能使用 jar 的 -C 參數來指定解壓的目標的,因為 -C 參數只在建立或者更新包的時候可用。那麼需要將檔案解壓到某個指定目錄下的時候就需要先將這具 JAR 檔案拷貝到目標目錄下,再進行解壓,比較麻煩。如果使用 unzip,就不需要這麼麻煩了,只需要指定一個 -d 參數即可。如:
unzip test.jar -d dest/
2) 使用 WinZip 或者 WinRAR 等工具建立 JAR 檔案
上面提到 JAR 檔案就是包含了 META-INF/MANIFEST 的 ZIP 檔案,所以,只需要使用 WinZip、WinRAR 等工具建立所需要 ZIP 壓縮包,再往這個 ZIP 壓縮包中添加一個包含 MANIFEST 檔案的 META-INF 目錄即可。對於使用 jar 命令的 -m 參數指定資訊清單檔的情況,只需要將這個 MANIFEST 按需要修改即可。
3) 使用 jar 命令建立 ZIP 檔案
有些 Linux 下提供了 unzip 命令,但沒有 zip 命令,所以需要可以對 ZIP 檔案進行解壓,即不能建立 ZIP 檔案。如要建立一個 ZIP 檔案,使用帶 -M 參數的 jar 命令即可,因為 -M 參數表示製作 JAR 包的時候不添加 MANIFEST 清單,那麼只需要在指定目標 JAR 檔案的地方將 .jar 副檔名改為 .zip 副檔名,建立的就是一個不折不扣的 ZIP 檔案了,如將上一節的第 3) 個例子略作改動:
jar cvfM test.zip test