Java的一些小知識:package,import,不同目錄下類的呼叫
這道題一共要建三個目錄:C:\myproj\bin、C:\myproj\lib和C:\myproj\classes,也可以自己建所要的目錄,三個目錄不同就可以了,具體要求如下:
n public的A.class和B.class屬於包X.Y,該包存放在C:\myproj\classes中;public的C.class和D.class屬於包S.T,把它們打包為E.jar檔案中,並存放在C:\myproj\lib中;這些類均有四個方法:public void sayPublic()、private void sayPrivate()、protected void sayProtected()、void sayDefault(),而且都只包含一條語句System.out.println("Hi,"+getClass()+"."+函式許可權(public|private|protected|default))。
n Test1.class、Test2.class和Test3.class為測試類(帶入口函式),存放在目錄C:\myproj\bin下。
n 打包命令:jar cvf K.jar * (注意把子目錄S/T也一起打包進去)。
(吐槽下,做實驗報告模板的老師或者TA這裡對這道題的表述有些混亂 == 至少我是這樣感覺的)
實驗步驟:
(1) Test1分別建立A和C的一個物件並呼叫這四個方法,看看哪些方法可以使用,不能使用的就註釋掉。
Test1執行截圖:
Test1的原始碼:
/*因為A.class和C.class不在Test1.java的所在目錄中,所以需要引用包進來, * 自動新增classpath在前之後,表示包位於 * H:\web\實驗\java實驗\lab3\code\classes\X\Y * 或 * H:\web\實驗\java實驗\lab3\code\lib\S\T * 下*/ import X.Y.*; import S.T.*; public class Test1{ public static void main(String[] args){ A a = new A(); a.sayPublic(); //a.sayPrivate(); //a.sayProtected(); //a.sayDefault(); C c = new C(); c.sayPublic(); //c.sayPrivate(); //c.sayProtected(); //c.sayDefault(); } }
(2)Test2繼承B並直接呼叫它的四個方法,看看哪些方法可以使用,不能使用的就註釋掉。
* 在main()中要採用“Test2 test2=new Test2(); test2.sayPublic();”進行呼叫,直接呼叫會出現 “無法從靜態上下文中引用非靜態方法”的錯誤(因為要呼叫非靜態方法,必須先要建立物件)。
Test2執行截圖:
Test2的原始碼:
/*因為B.class不在Test1.java的所在目錄中,所以需要引用包進來, * 自動新增classpath在前之後,表示包位於 * H:\web\實驗\java實驗\lab3\code\classes\X\Y * 下*/ import X.Y.*; //import S.T.*; public class Test2 extends B{ public static void main(String[] args){ Test2 test2 = new Test2(); test2.sayPublic(); test2.sayProtected(); //下面兩個無法引用(編譯時報錯) //test2.sayPrivate(); //test2.sayDefault(); } }
(3)Test3繼承D並直接呼叫它的四個方法,看看哪些方法可以使用,不能使用的就註釋掉。
Test3執行截圖:
Test3的原始碼:
/*因為D.class不在Test1.java的所在目錄中,所以需要引用包進來,
* 自動新增classpath在前之後,表示包位於
* H:\web\實驗\java實驗\lab3\code\lib\S\T
* 下*/
//import X.Y.*;
import S.T.*;
public class Test3 extends D{
public static void main(String[] args){
Test3 test3 = new Test3();
test3.sayPublic();
test3.sayProtected();
//同樣下面兩個無法引用(編譯時報錯)
//test3.sayPrivate();
//test3.sayDefault();
}
}
(4)A~D類的源程式。
A的源程式:
/*用package語句指明所屬包的名稱,
* 相當於註釋語句,只是告訴人說這些.java或.class在這個子目錄下*/
package X.Y;
public class A
{
public void sayPublic()
{
System.out.println("Hi,"+getClass()+ "."+ "public");
}
private void sayPrivate()
{
System.out.println("Hi,"+getClass()+ "."+ "private");
}
protected void sayProtected()
{
System.out.println("Hi,"+getClass()+ "."+ "protected");
}
void sayDefault()
{
System.out.println("Hi,"+getClass()+ "."+ "default");
}
}
B的源程式:
/*用package語句指明所屬包的名稱,
* 相當於註釋語句,只是告訴人說這些.java或.class在這個子目錄下*/
package X.Y;
public class B
{
public void sayPublic()
{
System.out.println("Hi,"+getClass()+ "."+ "public");
}
private void sayPrivate()
{
System.out.println("Hi,"+getClass()+ "."+ "private");
}
protected void sayProtected()
{
System.out.println("Hi,"+getClass()+ "."+ "protected");
}
void sayDefault()
{
System.out.println("Hi,"+getClass()+ "."+ "default");
}
}
C的源程式:
/*用package語句指明所屬包的名稱,
* 相當於註釋語句,只是告訴人說這些.java或.class在這個子目錄下*/
package S.T;
public class C
{
public void sayPublic()
{
System.out.println("Hi,"+getClass()+ "."+ "public");
}
private void sayPrivate()
{
System.out.println("Hi,"+getClass()+ "."+ "private");
}
protected void sayProtected()
{
System.out.println("Hi,"+getClass()+ "."+ "protected");
}
void sayDefault()
{
System.out.println("Hi,"+getClass()+ "."+ "default");
}
}
D的源程式:
/*用package語句指明所屬包的名稱,
* 相當於註釋語句,只是告訴人說這些.java或.class在這個子目錄下*/
package S.T;
public class D
{
public void sayPublic()
{
System.out.println("Hi,"+getClass()+ "."+ "public");
}
private void sayPrivate()
{
System.out.println("Hi,"+getClass()+ "."+ "private");
}
protected void sayProtected()
{
System.out.println("Hi,"+getClass()+ "."+ "protected");
}
void sayDefault()
{
System.out.println("Hi,"+getClass()+ "."+ "default");
}
}
通過上面的實驗,你可以得到什麼結論:
結論是對於一個類(如A),如果不是在同一個包中,那其他的類(如Test1)如果不是A的子類,那麼類Test1只能訪問A的public修飾的方法,如果Test1是A的子類,那麼它可以訪問A的public和protected修飾的方法。也就是老師PPT上列出的:
由於時間比較緊,因為現在已經快12點了,得趕著睡覺然後明天早起寫公選的讀書報告了,所以對於這次實驗就不在這裡寫詳細的解析了,這裡只複製下自己在做實驗過程彙總整理的一些word筆記,通過這些筆記也基本可以搞清楚這次實驗的相關知識和一些難點了:
1:這樣編譯C.java才能根據package語句自動新建子目錄並在子目錄生成.class檔案(得先進入到lib資料夾路徑裡才有效),兩種方法都行,第一種方法的”.”表示當前目錄:
其他的A.java B.java D.java也是同樣的方法。不用這種方法的話就無法根據package語句自動新建子目錄並在子目錄生成.class檔案,而要自己新建目錄並把.class檔案剪下到該目錄。
2:打包jar檔案首先cd到lib資料夾再輸入報告裡面那句程式碼(”jar cvf E.jar *”):
3:一定要把C.java和C.class檔案都放在子目錄下,然後再生成jar包(對於A.java B.jaba不用壓縮),然後再編譯Test1.java才能通過。不然報下面這樣的錯誤,為啥?
4:編譯Test1.java:先cd到bin目錄(即Test1.java所在目錄),再javac,同時中間要加上引用的A類和B類的包的路徑(最後的”;.”中的”.”表示把當前目錄也就是bin目錄也作為classpath納入進來,雖然並沒有用到這個目錄的.class檔案)
(這裡的截圖是把privated protected default的呼叫註釋掉了之後的,沒註釋掉的應該是下面的截圖,會報錯)
5:執行Test1.class: 同樣要加入classpath: