Java核心技術-對象與類
1 面向對象程序設計概述
面向對象的程序是由對象組成的,每個對象包含對用戶公開的特定功能部分和隱藏的實現部分。
1.1 類
類是構造對象的模板或藍圖,由類構造對象的過程稱為創建類的實例。
封裝:
從形式上看,是將數據和行為組合在一個包中,並對對象的使用者隱藏了數據的實現方式。
對象中的數據稱為實例域,操縱數據的過程稱為方法。
對於每個特定類實例(對象)都有一組特定的實例域值,這些值的集合就是這個對象的當前狀態。
實現封裝的關鍵在於絕對不能讓類中的方法直接地訪問其它類的實例域,程序僅能通過對象的方法與對象數據進行交互。
在Java中,所有類都源於一個“神通廣大的超類”,它就是Object。
通過擴展一個類來建立另一個類的過程稱為繼承。
1.2 對象
對象的三個主要特性:
對象的行為——可以對對象施加哪些操作,或可以對對象施加哪些方法。
對象的狀態——當施加那些方法時,對象如何響應。
對象的標識——如何辨別具有相同行為與狀態的不同對象。
1.3 識別類
識別類的簡單規則是在分析問題的過程中尋找名詞,而方法對應著動詞。
1.4 類之間的關系
在類之間,最常見的關系有
*依賴(“uses-a"):一個類的方法操縱另一個類的對象,我們就說一個類依賴於另一個類。減少依賴即減少耦合。
*聚合("has-a"):類A的對象包含類B的對象。
*繼承(”is-a"):用於表示特殊與一般關系的。
2 使用預定義類
2.1 對象與對象變量
要想使用對象,就必須首先構造對象,並指定其初始狀態。構造器是一種特殊的方法,用來構造並初始化對象。
構造器的名字應該與類名相同。
明白對象與對象變量之間的區別。
一定要認識到:一個對象並沒有實際包含一個對象,而僅僅引用一個對象。任何對象變量的值都是對存儲在另外一個地方的一個對象的引用。
局部變量不會自動初始化為null,而必須通過調用new或將他們設置為null進行初始化。
2.2 LocalDate類
Java中,Date類用來表示時間點,LocalDate類用來表示日歷表示法。
不要使用構造器來構造LocalDate類,應該使用靜態工廠方法代表你調用構造器:LocalDate.now()會構造一個表示構造這個對象時的日期對象。
2.3 更改器方法與訪問器方法
類似於String類的toUpperCase方法,調用這個方法時原對象不變,會返回一個將原對象中所有字符大寫的新對象。
相比較而言,那些會更改原對象狀態的方法稱為更改器方法。(GregorianCalendar.add)
訪問器方法:只訪問對象而不修改對象的方法。
3.用戶自定義類
實例域(private)+實例方法
3.1 構造器
*構造器與類同名
*每個類可以有一個以上的構造器
*構造器可以有0、1個或多個參數
*構造器沒有返回值
*構造器總是伴隨著new操作一起調用
3.2 隱式參數與顯示參數
一般方法有兩種參數,第一種參數稱為隱式參數,出現在方法名前的類對象。第二種顯示參數是位於方法名後面括號中的數值。
在每一個方法中,關鍵字this表示隱式參數。
3.3 封裝的優點
*一個私有的數據域
*一個公有的域訪問器方法
*一個公有的域更改器方法
註意不要編寫返回引用可變對象的訪問器方法,如果需要返回一個可變對象的引用,應該首先對它進行克隆。
public Date getHireDay(){
return (Date)hireDay.clone();
}
3.4 基於類的訪問權限
一個方法可以訪問所屬類的所有對象的私有域數據。
3.5 final實例域
final修飾符大都應用於基本類型域,或不可變類的域。
對於可變的類,final關鍵字只表示存儲在可變類對象中的對象引用不會再指向其它類對象,不過這個對象仍可以更改。(StringBuilder)
4 靜態域與靜態方法
4.1 靜態域(類域)
如果將域定義為static,那麽每個類中只有一個這樣的域。即使沒有一個類對象存在,靜態域也存在。它屬於類,而不屬於任何獨立的對象。
4.2 靜態常量
Math.PI、System.out
公有常量只能訪問不能修改:public final
system類有一個setOut方法看,可以將System.out(final變量)設置為不同的流,因為setOut方法是一個本地方法,不是用Java語言實現的,可以繞開Java語言的存取控制機制。
4.3 靜態方法
靜態方法是一種不能向對象實施操作的方法。
靜態方法不能訪問類的實例域,但是可以訪問自身類中的靜態域。
使用靜態方法的兩種情況:
* 一個方法不需要訪問對象狀態,其所需的參數都是通過顯示參數提供(Math.pow)
* 一個方法只需要訪問類的靜態域
4.4 工廠方法
靜態方法還有另一種常見的用途:靜態工廠方法——不通過 new
,而是用一個靜態方法來對外提供自身實例的方法
靜態工廠構造對象和構造器構造對象的主要區別(更靈活):
1.可以命名構造器名稱
2.不用每次被調用時都創建新對象
3.可以返回原返回類型的子類
5 方法參數
參數傳遞給方法的兩種方式:按值調用和按引用調用。
一個方法可以修改傳遞引用所對應的變量值,而不能修改傳遞值調用所對應的變量值。
Java采用按值調用。
方法參數兩種類型:
*基本數據類型
*對象引用
Java中方法參數的使用情況:
*一個方法不能修改一個基本數據類型的參數
*一個方法可以改變一個對象參數的狀態
*一個方法不能讓對象參數引用一個新的對象
6 對象構造
6.1 重載
由編譯器進行重載解析。
方法簽名:要完整地描述一個方法,需要指出方法名以及參數類型。(返回類型不是方法簽名的一部分)
6.2 默認域初始化
如果在構造器中沒有顯式地給域賦予初值,那麽就會被自動地賦為默認值:數值為0、布爾值為false、對象引用為null。
這是域與局部變量的主要不同點——局部變量沒有默認初始化,必須顯示的初始化局部變量。
6.3 無參數構造器
如果類中提供了至少一個構造器,但是沒有提供無參數的構造器,則在構造對象時沒有提供參數就會被認為不合法。
僅當類中沒有提供任何構造器,系統才會提供一個默認構造器。
6.4 調用另一個構造器
如果構造器的第一個語句形如this(),這個構造器將調用同一個類的另一個構造器。
6.5 初始化塊
初始化數據域的方法:
1.在構造器中設置值
2.在聲明中賦值
3.初始化塊
調用構造器初始化的步驟:
所有數據域被初始化為默認值(靜態域初始化)->數據域初始化語句->初始化塊->構造器
6.6 對象析構器與finalize方法
finalize方法將在垃圾回收器清除對象之前調用。
如果某個資源需要在使用完畢後立刻關閉,可以應用一個close方法來完成相應的清理操作。
7 包
使用包的主要原因是確保類名的唯一性。
7.1 類的導入
一個類可以使用所屬包中的所有類,以及其它包中的公有類。
只能使用星號(*)導入一個包,而不能使用import java.*或import java.*.*導入以java為前綴的所有包。
可以采用增加一個特定的包名解決兩個包中共有類的引用問題。
如果兩個包中的兩個相同名稱的類都要引用,可以在每個類名前加上完整的包名。
7.2 靜態導入
import語句不僅可以導入類,還增加了導入靜態方法和靜態域的功能。
7.3 將類放入包中
編譯器對文件(帶有文件分隔符和擴展名.java的文件)進行操作。而Java解釋器加載類(帶有.分隔符)
7.4 包作用域
標記為public的部分可以被任意的類使用;標記為private的部分只能被定義它們的類使用。如果沒有指定public或private,這個部分(類、方法、變量)可以被同一個包中的所有方法訪問。
8 類設計技巧
1.一定要保證數據私有
2.一定要對數據初始化
3.不要在類中使用過多的基本類型
4.不是所有的域都需要獨立的域訪問器和域更改器
5.將職責過多的類進行分解
6.類名和方法名要能體現它們的職責
7.優先使用不可變的類(考慮具體情況)
Java核心技術-對象與類