java程式設計--孫鑫java無難事Lesson3《包、類和方法說明符、記憶體回收、介面》
本節要點:
1.包
2.類的說明符
3.方法的說明符
4.對象的銷毀(垃圾記憶體回收的示範)
5.介面
//*********************************************************************************
主要內容:
1.包的作用--解決類名衝突,類似於檔案系統的目錄系統。
(1)使用包名而編譯時間沒有指定包名時,會出錯,錯誤資訊如下:
F:\java\JavaLesson\Lesson3>javac Test.java
F:\java\JavaLesson\Lesson3>java Test
//*********************************************************************************
Exception in thread "main" java.lang.NoClassDefFoundError: Test (wrong name: pac
ktest/Test)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
...
(2)包名對應一個檔案目錄名,沒有組建目錄時,會出錯,錯誤資訊如下:
F:\java\JavaLesson\Lesson3>java packtest.Test
錯誤: 找不到或無法載入主類 packtest.Test
解決方案一:
手動建立一個目錄來解決問題。
F:\java\JavaLesson\Lesson3>java packtest.Test
pakage test!
解決方案二:使用javac -d .參數
javac -d .t Test.java //目前的目錄建立檔案夾
-d 參數使用:
在目前的目錄下產生包
javac –d . Test.java
在指定目錄下產生包
javac –d E:\JavaLesson Test.java
(3)引入包
a.引入類 import java.io.File
b.引入整個包 import java.io.* ,匯入所有類時java編譯器需要額外記憶體來跟蹤包中類資訊
c.在同一個包中的類可以相互引用,無需import語句
d.java的lang包自動匯入,自己類要手動匯入.
不再同一個包時無法直接引用,錯誤如下:
Test.java:10: 錯誤: 找不到符號
Test2 test=new Test2();
符號: 類 Test2
位置: 類 Test
2.類的說明符
(1)類的訪問說明符
a.public
b.default(不加訪問說明符時)
(2)類的其它修飾符
a.final
final最終類,無法派生子類.
試圖從最終類派生,會出錯,錯誤的繼承資訊為:
//*********************************************************************************
F:\java\JavaLesson\Lesson3>javac -d . Test.java
Test.java:6: 錯誤: 無法從最終Test2進行繼承
class Test extends Test2
b.abstract
c.編譯使用萬用字元 javac -d . *.java
(3)類名沒有加說明符時為預設類,不是public類型的,在包外無法訪問。預設類只能在同一個包中被訪問。
執行語句:
F:\java\JavaLesson\Lesson3>javac -d . Test2.java
F:\java\JavaLesson\Lesson3>javac -d . Test.java
錯誤資訊如下:
//*********************************************************************************
Test.java:5: 錯誤: Test2在qq.test2中不是公用的; 無法從外部程式包中對其進行訪問 import qq.test2.Test
Test.java:11: 錯誤: 找不到符號 Test2 test=new Test2();
符號: 類 Test2
位置: 類 Test
解決方案:將類聲明為public.
3.方法說明符
(1)說明符
方法的訪問說明符
public
、protected
、default(不加訪問說明符時)
、private方法的其它修飾符
static
、final
、abstract
、native
、synchronized
(2)同一個類中 所有方法均可調用
同類中方法訪問測試程式,運行效果
//*********************************************************************************
F:\java\JavaLesson\Lesson3>java qq.packtest.Test
public Method
protected Method
default Method
private Method
(3) 同一個包中 不可以訪問private方法即使是繼承的類也不可以 但是可以訪問default方法.
試圖訪問private方法錯誤資訊如下:
F:\java\JavaLesson\Lesson3>javac -d . Test2.java
Test2.java:12: 錯誤: priMethod()可以在Test中訪問private test.priMethod();
(4) 不同的包中 繼承的類可以訪問public和protected方法,但是default和private方法均不可以訪
(5) 不同的包也不存在繼承關係時
除了公有public方法外,均不可以訪問。
試圖訪問除public方法外的方法時,錯誤資訊如下:
//*********************************************************************************
F:\java\JavaLesson\Lesson3>javac -d . Test2.java
Test2.java:29: 錯誤: proMethod()可以在Test中訪問protected
test.proMethod();
Test2.java:30: 錯誤: defMethod()在Test中不是公用的; 無法從外部程式包中對其進行訪問
test.defMethod();
Test2.java:31: 錯誤: priMethod()可以在Test中訪問private
test.priMethod();
存取權限總結見所示:
(6)final方法
a.為了確保某個函數的行為在繼承過程中保持不變,並且不能被覆蓋(overridden),可以使用final方法。
試圖重載父類final方法,錯誤資訊如下:
F:\java\JavaLesson\Lesson3>javac -d . Test2.java
Test2.java:7: 錯誤: Test2中的pubMethod()無法覆蓋Test中的pubMethod()public void pubMethod()被覆蓋的方法為finalb.為了效率上的考慮,將方法聲明為final,讓編譯器對此方法的調用進行最佳化。要注意的是:編譯器會自行對final方法進行判斷,並決定是否進行最佳化。通常在方法的體積很小,而我們確實不希望它被覆蓋時,才將它聲明為final。
c.class中所有的private和static方法自然就是final。
4.抽象方法和抽象類別
a.在類中沒有方法體的方法,就是抽象方法。b.含有抽象方法的類,即為抽象類別。
c.如果一個子類沒有實現抽象基類中所有的抽象方法,則子類也成為一個抽象類別。
d.我們可以將一個沒有任何抽象方法的類聲明為abstract,避免由這個類產生任何的對象。
e.構造方法、靜態方法、私人方法、final方法不能被聲明為抽象的方法。
常見錯誤:
a.定義了抽象方法而沒有聲明為抽象類別.
F:\java\JavaLesson\Lesson3>javac -d . Test.java
Test.java:6: 錯誤: Test不是抽象的, 並且未覆蓋Test中的抽象方法proMethod()
public class Test //extends Test2
b.抽象類別無法執行個體化對象
執行語句:
F:\java\JavaLesson\Lesson3>javac -d . Test.java
錯誤資訊如下:
Test.java:44: 錯誤: Test是抽象的; 無法執行個體化
Test test= new Test();
c.子類繼承了父類的抽象方法而沒有重載抽象方法時出錯
錯誤資訊如下:
//*********************************************************************************
F:\java\JavaLesson\Lesson3>javac -d . Test2.java
Test2.java:5: 錯誤: Test2不是抽象的, 並且未覆蓋Test中的抽象方法proMethod()
public class Test2 extends Test
5.JNI
a.JNI(Java Native Interface),它允許Java虛擬機器(JVM)內部啟動並執行Java代碼能夠與用其它程式設計語言(如C、C++、組合語言)編寫的應用程式和庫進行互操作。b.JNI最大的好處是它沒有對底層Java虛擬機器的實現施加任何限制,因此,Java虛擬機器廠商可以在不影響虛擬機器其它部分的情況下添加對JNI的支援。程式員只需編寫一種版本的本地(Native)應用程式和庫,就能夠與所有支援JNI的Java虛擬機器協同工作。
c.JNI可以理解為Java和本地應用程式之間的中介。
d.native方法是使用者在Java中可以使用,但不能編寫的方法。關於JNI後續學習再做瞭解.
6.記憶體回收機制分析
a.記憶體回收一般不會自動調用,記憶體不足時系統將運行記憶體回收
b.要讓記憶體回收運行,需要顯式調用System.gc();
c.記憶體回收的過程不唯一,以下測試代碼運行結果可能不同。
記憶體回收機制測試代碼為:
//*********************************************************************************
class Garbage
{
int index;
static int cnt;
Garbage()
{
cnt++;
System.out.println("object"+cnt+" constructed");
SetId(cnt);
}
void SetId(int id)
{
index=id;
}
//記憶體回收時調用此函數
protected void finalize()
{
System.out.println("object"+index+" reclaimed");
}
public static void main(String[] args)
{
new Garbage();
new Garbage();
new Garbage();
new Garbage();
System.gc();//顯式調用記憶體回收行程
}
}
//*********************************************************************************
示範結果:
object1 constructed
object2 constructed
object3 constructed
object4 constructed
object4 reclaimed
object3 reclaimed
object2 reclaimed
object1 reclaimed
7.介面 ---解決開發過程中的開發人員的協調問題,統一模組間的通訊。
a.介面中所有方法都是abstract、public。
b.在實作類別中實現方法中,存取權限不能低於介面的存取權限。
否則出錯,錯誤資訊如下:
Sport.java:12: 錯誤: Athlete中的jump()無法實現Sport中的jump()
void jump()
正在嘗試分配更低的存取權限; 以前為public
Sport.java:8: 錯誤: Athlete中的run()無法實現Sport中的run()
void run()
正在嘗試分配更低的存取權限; 以前為public
c.介面中可以有資料成員,這些成員預設都是public static final,即公有靜態常量。
//*********************************************************************************
interface Math
{
double PI=3.1415926; //預設都是public static final 公有靜態常量
double roundArea(double radius);//介面
}
class Arithmetic implements Math //實現介面
{
public double roundArea(double radius)//需為public
{
return PI*radius*radius;
}
}
class Student
{
public static void main(String[] args)
{
Arithmetic a=new Arithmetic();
System.out.println(a.roundArea(3));
//訪問靜態成員變數
System.out.println(Math.PI); //ok
System.out.println(Arithmetic.PI);//ok
System.out.println(a.PI);//ok
}
}
d.介面實現1
介面實現示範代碼如下:
//*********************************************************************************
interface Sport //定義介面
{
void run();
void jump();
}
class Athlete implements Sport //實現介面
{
//介面存取權限為公有
public void run()
{
System.out.println("短跑");
}
//如果定義的類想執行個體化對象,必須實現介面中所有方法
public void jump()
{
System.out.println("三級跳");
}
public static void main(String[] args)
{
Athlete ath=new Athlete();
ath.run();
ath.jump();
}
}
//*********************************************************************************
//運行效果
F:\java\JavaLesson\Lesson3>javac Sport.java
F:\java\JavaLesson\Lesson3>java Athlete
短跑
三級跳
e.介面實現2 實現介面時,介面中的所有方法均要實現,否則出錯,錯誤資訊如下:
Sport.java:6: 錯誤: Athlete不是抽象的, 並且未覆蓋Sport中的抽象方法jump()
class Athlete implements Sport //實現介面
Sport.java:23: 錯誤: 找不到符號
ath.jump();
符號: 方法 jump()
位置: 類型為Athlete的變數 ath
f.介面概念深入理解代碼如下:
//*********************************************************************************
interface VideoCard //顯卡介面
{
void display();//顯示
String getname();//擷取產品名稱
}
class MainBoard //主板
{
String strcpu;
VideoCard vc;//只管定義顯卡 不管由誰製造
void setcpu(String strcpu)
{
this.strcpu=strcpu;
}
void setvideocard(VideoCard vc)
{
this.vc=vc;
}
void run()
{
System.out.println(strcpu);
System.out.println(vc.getname());
vc.display();//只管調用介面
System.out.println("mainboard is running!");
}
}
class Dmeng implements VideoCard //Dmeng顯卡製造商實現顯卡
{
String name;
//實現顯示
public void display()
{
System.out.println("Dmen's video is working!");
}
//實現擷取名稱
public String getname()
{
return name;
}
public Dmeng()
{
name="Dmeng video";
}
void setname(String str)
{
name=str;
}
}
class Computer //電腦
{
public static void main(String[] args)
{
Dmeng dm=new Dmeng();//顯卡
MainBoard mb=new MainBoard();//主板
mb.setcpu("Intel's cpu");//設定cpu
mb.setvideocard(dm);//設定顯卡
mb.run();//運作
}
}
//*********************************************************************************
//運行結果
Intel's cpu
Dmeng video
Dmen's video is working!
mainboard is running!
8.介面與類的繼承
a.java不支援類的多繼承
示範代碼如下:
//*********************************************************************************
class Animal
{
//動物呼吸
void Breath(){}
}
class Fish
{ //魚類遊動
void Swim(){}
}
class whale extends Animal ,Fish //error java不支援類的多繼承
{
//鯨魚噴水
void Blow(){}
}
//*********************************************************************************
錯誤資訊如下:
ClassExtends.java:15: 錯誤: 需要'{'
class whale extends Animal ,Fish
b.java允許一個類實現多個介面
//*********************************************************************************
interface Sittable
{
void sit();
}
interface Lie
{
void sleep();
}
class Sofa implements Sittable, Lie //ok 允許一個類實現多個介面
{
public void sit(){}
public void sleep(){}
}
c.java允許介面的多繼承
//*********************************************************************************
interface Sittable
{
void sit();
}
interface Lie
{
void sleep();
}
interface Chair extends Sittable //介面繼承仍然使用extends
{
}
interface Sofa extends Sittable, Lie //ok 允許介面的多繼承
{
}
d.java允許在繼承類的同時,實現多個介面
//*********************************************************************************
interface Sittable
{
void sit();
}
interface Lie
{
void sleep();
}
interface HealthCare
{
void massage();
}
class Chair implements Sittable
{
public void sit(){};
}
class Sofa extends Chair implements Lie, HealthCare //ok 允許在繼承類的同時,實現多個介面
{
public void sleep(){};
public void massage(){};
}