程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> [Java學習筆記] Java核心技術 卷1 第四章,學習筆記核心技術

[Java學習筆記] Java核心技術 卷1 第四章,學習筆記核心技術

編輯:JAVA綜合教程

[Java學習筆記] Java核心技術 卷1 第四章,學習筆記核心技術


 

 

第4章 對象與類

4.1 類和對象的基本概念

描述了類和對象的基本概念,以及類之間的關系介紹。

程序中的很多對象來自於標准庫,還有一些自定義的。

結構化程序設計:通過設計一系列的過程(算法),選擇合適的存儲方式來解決問題。 算法+數據結構

4.1.1 類/封裝/繼承

類是構造對象的模板,由類構造對象的過程稱為創建類的實例。

封裝:也稱為數據隱藏。從形式上看,封裝不過是將數據和行為組合在一個包中,並對對象的使用者隱藏了數據的實現方式。優點4.2.3

實例域:對象中的數據。

方法:操縱數據的過程。

對於每個特定的對象都有一組特定的實例域值。這些值的集合就是這個對象的當前狀態。

實現封裝的關鍵在與絕對不能讓類中的方法直接地訪問其他類的實例域。程序僅通過對象的方法與對象數據進行交互。這是提高重用性和可靠性的關鍵。

繼承:通過擴展一個類來建立另外一個新的類。

在擴展一個已有的類時,這個擴展後的新類具有所擴展的類的全部屬性和方法。

Java中一個源文件只能包含一個公有類並且文件名必須與共有類匹配。

4.1.2 對象的特性

對象的行為:對象的方法。同一個類的所有對象實例,具有相同的方法而獲得家族式的相似性。

對象的狀態:當使用方法時對象如何響應。對象的狀態描述當前對象的特征信息,狀態只能通過調用方法來改變(否則說明封裝性遭到了破壞)。

對象標識:對象的狀態並不能完全描述一個對象。每個對象都有一個唯一的身份。

4.1.3 類之間的關系

依賴:use-a ,類A的方法操縱類B的對象,A依賴賴於B。相互依賴最少,耦合度最小。

聚合:has-a ,類A的對象包含類B的對象。

繼承:is-a ,一般到特殊,

使用UML繪制類圖,描述類之間的關系。

4.2 如何使用類

4.2.1 對象與對象變量

所有的Java對象都存儲在堆中。

使用構造器構造並初始化對象。

對象變量並不包含一個對象,對象變量的值只是對存儲在別處某個對象的引用。new的返回值也是一個引用。當一個對象包含另一個對象變量時,這個變量依然僅包含指向另一個堆對象的指針。

(引用相當於指針,內存地址)

Date date= new Date();
Date dead=null;
如果dead=date,則dead引用了與date相同對象。

4.2.2 不鼓勵使用的方法

當類庫設計者意識到某個方法不應該存在時,就把它標記為不鼓勵使用,雖然在程序中仍然可以使用,但編譯時會出現警告,而且有可能會在未來的類庫版本中刪除。

4.3 設計類

4.3.1 構造器

訪問級別:方法可以訪問所屬類的私有特性,

構造器:與類同名;至少一個;不限制參數數量;沒有返回值;總是使用new操作來調用。

4.3.2 實例域

將所有的數據域設為私有,同時設置訪問器與更改器實現對數據域的訪問和修改。

私有的數據域、公有的更改器與訪問器實現了封裝,帶來的好處有:

1:可以改變內部實現,除了該類的方法之外不會影響其他代碼

2:更改器方法可以執行錯誤檢查

如果訪問器要返回一個可變對象的引用,需要先對對象克隆,然後返回克隆後的對象。如下列情況

Employee em= ... ; Date d= em.getDate(); getDate作為訪問器返回了em中一個私有的日期對象,但d也引用了相同的對象,對d操作可以改變em中的值,破壞了封裝。

final實例域

可以將實例域定義為final,構建對象時必須對其初始化,且之後的操作中不能在對其修改。

final修飾符大多應用於基本類型或不可變類的域(類中的每個方法都不改變其對象如String類)

4.3.3 方法

對外的方法設置為公有,類內的輔助方法設置為私有。

對於類的設計者而言,公有的方法一定不可以刪去,因為其他的代碼可能訪問到,私有的可以被刪去

4.3.4 靜態域

將域定義為static,則類中只有一個這樣的域,每個對象共享靜態域,即使沒有對象域也會存在,它屬於類不屬於對象。使用類名訪問。 Math.PI

靜態常量:public static final double PI,靜態常量不會被修改,所以設置為public

4.3.5 靜態方法

通過類使用,不能對對象使用。

因為靜態方法不能操作對象,所以不能在靜態方法中訪問實例域。但是可以訪問類中的靜態域。

當一個方法不需要訪問對象狀態,其參數都通過顯示參數提供或只需訪問類中的靜態域則可設置為靜態方法。

l  工廠方法

靜態方法的一種用途。

如NumberFormat.getCurrnecyInstance(); NumberFormat.getPercentInstance();

無法命名構造器,構造器的名字必須與類名相同,但這裡希望得到貨幣實例和百分比時采用不同的名字。

當使用構造器時,無法改變所構造的對象類型。

4.3.6 方法參數

按值調用:接收調用者提供的值;按引用調用:接收調用者提供的變量地址。

方法可以修改傳遞引用所對應的變量值,而不能修改傳遞值調用所對應的變量值。

Java總是按值調用。方法得到的所有參數值是一個拷貝,對象引用及其他的拷貝同時引用一個對象,方法不能修改傳遞給它的任何參數變量的內容。

"引用"是一個需要內存A存儲的"值",方法的參數獲得了該"值"的一個副本存儲在新的內存B中,方法結束後內存B棄用,仍然沒有更改原來內存A中的"值"。

方法內使用的參數與傳進去的參數在不同的內存中存儲了相同的"引用"的值,該"引用"又指向了某內存塊,該內存塊實際記錄對象裡各個實例域的值,對方法內使用的參數的"引用"使用更改器,改變的是內存塊中的值,原來的"引用"也是指向這塊存儲內容變化過的內存塊,所以實現了改變對象參數的狀態。

public static void swap(Employee x,Employee y)
{
   Employee temp=x; x=y;y=temp;
}
並不會交換傳入的兩個對象。因為x和y並沒有引用原來的對象,而是復制了原來對象的"值(地址)",交換的是x和y
即使是swap(int x,int y)也不會成功。

 

4.4 對象構造

4.4.1 重載

多個方法具有相同的名字、不同的參數。方法名與參數類型叫做方法的簽名。

返回類型不屬於方法簽名,不能有兩個名字相同、參數類型相同卻返回不同類型值的方法。

4.4.2 默認域初始化

如果在構造器中沒有顯式的給域賦初值,會自動為域賦為默認值。

局部變量必須明確初始化,而域如果沒有初始化會被自動初始化為默認值。

4.4.3 無參數的構造器

對象由無參數構造器創建時,狀態會設置為適當的默認值。

只有類中沒有提供任何構造器的時候,系統才會提供一個默認的構造器。也就是說如果提供了一個帶參數的構造器而未提供不帶參數的,系統不會自動提供不帶參數的構造器,在使用不帶參數的構造器時會報錯。

4.4.4 顯示域初始化

確保不管怎樣調用構造器,每個實例域都可以被設置為一個有意義的初值是一種很好的設計習慣。

初始值不一定是常量。可以調用方法對域進行初始化。

4.4.5 調用另一個構造器

構造器的第一個語句形如 this(...),這個構造器將調用同一個類的另一個構造器,括號內為參數列表,根據參數選擇是哪一個構造器。

public Employee(double s)
{ 
  //calls Employee(String,double)...
  this("Employee ",s);
  ...
}

4.4.6 初始化塊

在一個類的聲明中,可以包含多個代碼塊,只要構造類的對象,這些塊就會被執行。如:

Class Employee
{
  private static int nextID;   private int id;   private String name;   {id=nextID} //初始化塊   public Employee()...   public Employee(String s,int i).. } 無論執行哪個構造器,都會先執行 id=nextID代碼塊

4.4.7 構造器的處理步驟

基於上述多個途徑下的步驟:

1:所有數據域被初始化為默認值。

2:按照在類聲明中出現的次序,依次指向所有域初始化語句和初始化塊。

3:如果構造器第一行調用了第二個構造器,則執行第二個構造器主體。

4:執行這個構造器的主體。

4.4.8 對象析構

Java有自動的垃圾回收,不支持析構器。

finalize方法將在垃圾回收器清除對象之前調用,在實際應用中不要依賴使用finalize方法回收任何短缺的資源,因為很難知道這個方法什麼時候才能夠調用。

對於需要在使用完畢後立刻被關閉的資源(如文件),在對象用完時應用close方法來完成清理操作。

4.5 包

Java允許使用包將類組織起來,同時可以確保類名唯一性。

為了保證包名的絕對唯一性,Sun公司建議將公司的因特網域名以逆序的形式作為包名。並對不同的項目使用不同的子包。

4.5.1 類的導入

java.lang包被默認導入。

一個類可以使用所屬包中的所有類,以及其他包中的公有類。

使用import 語句導入一個特定的類或者整個包 如 import java.util.*;

import java.util.* 與import java.util.Date; 相比對代碼的大小沒有任何負面影響。

使用星號只能導入一個包,而非以其前綴的所有包。

大多數情況下只導入所需的包,但在發生命名沖突時需要考慮。如果只用一個則把那一個精准導入,否則在使用類時前面加上完整的包名。

import語句的唯一好處是便捷。

Eclipse中 Source – Organize Imports Pagckage

4.5.2 靜態導入

import不僅可以導入類,還可以導入靜態方法和靜態域。

如 import static java.lang.System.*; 則可直接使用out.println(...);

4.5.3 將類放入包中

在源文件的開頭,寫上  package  包名 ;

4.5.4 包的作用域

變量顯示private,

類、方法、變量若沒有設置訪問修飾符則包中的所有方法都可以訪問。

包密封機制將各種包混雜在一起,不能再向這個包添加類了。

4.6 類路徑

類存儲在文件系統的子目錄中。類的路徑必須與包名匹配。

類文件也可以存儲在JAR(Java歸檔)文件中。在一個JAR文件中,可以包含多個壓縮形式的類文件和子目錄。

為了使類能夠被多個程序共享,需要以下幾點:

1:把類放到一個目錄中,這個目錄是包樹狀結構的基目錄。

2:將JAR文件放在一個目錄中

3:設置類路徑。類路徑是所有包含類文件的路徑的集合。基目錄/當前目錄/JAR文件

編譯器定位文件,如果引用了一個類而沒支出這個類所在的包,編譯器首先查找包含這個類的包,並詢查所有import執行,確定其中是否包含了被引用的類。如果找到一個以上的類就會產生編譯錯誤,類必須是唯一的,而import語句的次序卻無關緊要。

之後還要查看源文件是否比類文件新,如果是那麼源文件就會被自動地重新編譯。由於只能導入其他包中的公有類而一個源文件只包含一個共有類,所以編譯器很容易定位源文件。如果從當前包中導入了一個類,編譯器就要搜索當前包中的所有源文件,以便確定哪個源文件定義了這個類。

4.7 文檔注釋

4.7.1 注釋的插入

javadoc,可以由源文件生產一個HTML文檔。 javadoc utility從下面幾個特性中抽取信息:

公有類和接口

公有的和受保護的構造器及方法

公有的和受保護的域

注釋以/** 開始 以 */結束 。自由格式文本。標記由@開始

4.7.2 類注釋

類注釋必須放在import之後,類定義之前。

4.7.3 方法注釋

方法注釋必須放在所描述的方法之前,除通用標記之外還可以使用下面的標記

@param 變量描述 可占據多行,可使用html標記,但一個方法的所有@param標記必須放在一起

@return 描述 對當前方法添加 return 部分,可跨多行可使用html標記

@throws類描述 這個標記將添加一個注釋,用於表示這個方法可能拋出異常。、

4.7.4 域注釋

只需要對公有域(通常只的是靜態常量)建立文檔

4.7.5 通用注釋

以下可用在類文檔的注釋中

@auther 姓名

@version 版本

@since 始於

@deprecated 類、方法、變量等添加不再使用的注釋

@see 引用 用於類、方法中,添加一個超鏈接。

4.7.6 包與概述注釋

可以直接將類、方法和變量注釋放在java源文件中,只要以/** ..*/為界就可以了。但想要產生包注釋就需要在每個包目錄添加一個單獨的文件:

1:提供一個以package.html命名的html文件,在body裡的所有文本都會被抽取

2:提供一個以package-info.java命名的java文件,這個文件必須包含一個初始的以/** .. */為界定的Javadoc注釋,跟隨在一個包語句之後。它不應該包含更多的代碼或注釋。

還可以為所有的源文件添加一個概述性的注釋,該注釋放置在一個名為overview.html的文件中,並包含在所有源文件的父目錄中。body裡的所有文本都會被抽取。

4.8 類設計技巧

1:一定要保證數據私有

2:一定要對數據初始化

3:不要在類中使用過多的基本類型

4:不是所有的域都需要設置獨立的域訪問器和域更改器

5:將職責過多的類進行分解

6:類名和方法名要能夠體現它們的職責

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved