SlideShare uma empresa Scribd logo
1 de 119
第 9 章

物件的建構
本投影片(下稱教用資源)僅授權給採用教用資源相關之旗標書籍為教科書之授課老師(下稱老師)專用,老
師為教學使用之目的,得摘錄、編輯、重製教用資源(但使用量不得超過各該教用資源內容之 80% )以製作為
輔助教學之教學投影片,並於授課時搭配旗標書籍公開播放,但不得為網際網路公開傳輸之遠距教學、網路教
學等之使用;除此之外,老師不得再授權予任何第三人使用,並不得將依此授權所製作之教學投影片之相關著
作物移作他用。
著作權所有 © 旗標出版股份有限公司
學習目標
 撰寫建構物件的方法
 成員變數的存取控制
 在相同類別的不同物件間共享資料
前言
 前一章學習了定義類別、使用物件的基本方式。但由
上一章所學 , 在程式中使用物件時仍相當不便 , 感覺
也相當不『物件導向』。
 以前一章範例程式中所用的汽車類別為例 , 每次建立
物件後 , 都還要在 main() 方法中另行設定物件的成
員變數的值。
前言
前言
 如果可以將建立物件與設定物件狀態的動作結合在一
起 , 會有以下優點:
▪ 避免忘記設定物件初始狀態 , 這種錯誤看起來雖然是小事 ,
但往往在程式出錯時也最容易忽略。由於編譯器無法猜測
物件在產生後是否需要進行任何初始化的動作 , 因此無法
像是警告您變數尚未設定初值的方式提出警示。
▪ 更接近自然界的物件。舉例來說 , 小嬰孩必定在出生前就
決定了膚色與髮色 , 而不會是先出生 , 然後才顯現膚色或
是髮色;相同的道理 , 舞台劇上場的演員也不會先出場 ,
然後請觀眾等一下 , 在台上上妝之後才開始演出。既然如
此 , 程式中的各個物件也應該在產生的同時就設定好初始
狀態 , 直接參與程式的執行。
前言
 為了解決上述的問題 , Java 這一類物件導向的程式
語言便提供一個特別的機制 , 來幫物件設定初始狀態
, 而這也就是本章的主題。
9-1 建構方法 (Constructor)
 建構方法就是物件導向程式語言對於物件初始化的解
決方案。
 顧名思義 , 建構方法是一個方法 (method), 比較特
別的是:它是在建立物件時由系統自動呼叫 , 以建構
物件初始的狀態 , 因此名之為建構方法。
 也因為在物件產生時會自動呼叫建構方法 , 因此使用
new 運算子時 , 才必須在類別的名稱之後加上一對
小括號 , 這對小括號的意義就是呼叫建構方法。
9-1-1 預設建構方法 (Default Constructor)
 建構方法的名稱與類別名稱相同 , 如果類別之中並未
定義任何建構方法 , 則 Java 編譯器會自動幫類別定
義一個預設建構方法 , 例如:
預設建構方法 (Default Constructor)
 在上面這個例子中 , Test 類別就沒有定義任何的建構
方法 , 因此 Java 編譯器便會自動定義一個預設的建
構方法 , 此時就如同以下的程式:
預設建構方法 (Default Constructor)

 第 5 〜 6 行就是一個建構方法 , 但這個建構方法什
麼事情都沒有做 , 單純只是為了類別必須定義有建構
方法而存在。
 也正因為如此 , 如果類別在產生物件的時候並不需要
進行任何初始化的動作 , 撰寫時就可以省略定義建構
方法 , 讓 Java 編譯器自動替我們產生。
9-1-2 自行定義建構方法
 如果需要對新建立的物件進行任何初始化設定 , 那麼
就可以自行定義建構方法。
 定義建構方法時除了要依循一般方法的定義規則外 ,
還有以下幾點需要注意:
▪ 建構方法不能傳回任何值 , 因此不需也不能註明傳回
值 型別 , 連 void 也不可加上 , 如果加上傳回型別 ,
反而會造成編譯錯誤。
▪ 建構方法一定要和類別同名 , 而不可使用其他名稱。
無參數的建構方法
 最簡單的建構方法就是在方法的主體區塊中對物件進
行初始化的設定 , 例如:
無參數的建構方法
無參數的建構方法
 在程式第 14 行一樣是用 new 運算子建立物件 , 由
於 Java 會自動呼叫第 5 〜 8 行的建構方法 , 所以
成員變數 x 與 y 都被設為指定的值 , 並不需要在產
生物件之後另外指定。
具有參數的建構方法
 建構方法也可接受參數 , 讓物件的建構時更具彈性。
 建構方法若能接受參數 , 在建立物件時 , 就可以透過
跟隨在 new 運算子以及類別名稱之後的那一對小括
號傳入參數。例如:
具有參數的建構方法
具有參數的建構方法
 要特別注意的是 , 一旦定義了建構方法之後 , 使用
new 運算子產生物件時就必須依據建構方法的定義 ,
傳入相同數量以及型別的參數 , 就像是呼叫一般的方
法一樣 , 否則編譯時就會產生錯誤 , 例如:
具有參數的建構方法
具有參數的建構方法
 編譯後的錯誤訊息告訴我們 , 編譯器找不到僅需要單
一個整數的建構方法。
9-1-3 建構方法的多重定義 (Overloading)
 建構方法也和一般的方法一樣 , 可以使用多重定義的
方式 , 定義多種版本的建構方法 , 以便能夠依據不同
的場合 , 為新產生的物件進行最適當的初始設定。
 編譯器會依據所傳入參數的個數以及資料型別 , 選擇
符合的建構方法 , 就像是編譯器選擇多重定義的一般
方法時一樣。
 舉例來說 , 底下的類別就同時定義有多個版本的建構
方法:
建構方法的多重定義 (Overloading)
建構方法的多重定義 (Overloading)
建構方法的多重定義 (Overloading)

 在此範例中 , Test 類別擁有 3 種版本的建構方法 ,
如此就可以依據需要 , 使用適當的建構方法。
建構方法的多重定義 (Overloading)
 有一點需要特別注意:當我們為類別定義需要參數的
建構方法時 , Java 編譯器就不會替我們建立無參數
的預設建構方法 , 因此這時候最好也自行為類別加上
一個不需參數的建構方法。
 因為當程式產生物件時 , 未必每次都需要將物件設定
為特定狀態 , 此時這個不需參數的建構方法就可以提
供一種預設狀 態給物件 , 撰寫程式時就可以享有一定
程度的方便性。
 因此 , 建議在為類別設計建構方法時 , 先定義一個不
具參數的建構方法 , 可以將物件設定為預設的狀態。
接著 , 再根據不同的情況 , 定義特殊的版本。
9-1-4 this 保留字
 由於建構方法主要的用途是設定物件的初始狀態 , 傳
入的參數大多與類別的成員變數相關 , 因此在為這些
參數命名時通常都會和成員變數相同 , 這時就和一般
的方法一樣 , 參數的名稱會遮蔽掉 (Shadowing) 成
員變數。
 如果需要存取成員時 , 就可以使用上一章介紹過的
this 保留字 , 以表示目前執行此方法的物件 , 例如
。
this 保留字
this 保留字
 除了在參數名稱與成員名稱相同的情況派上用場外 ,
this 保留字還有一個很大的妙用。
 如果在建構方法中所需要進行的設定 , 有一部份在另
外一個版本的建構方法中完全重複 , 而想要在直接呼
叫該版本的建構方法時 , 並不能直接使用類別名稱呼
叫該建構方法。
this 保留字
this 保留字
this 保留字
 在第 6 行中 , 本來想要利用另一個只需單一參數的
建構方法設定成員變數 x 的值 , 但是從編譯後的錯
誤訊息說明了編譯器找不到一個叫做 Test() 的方法
。
 換句話說 , 雖然建構方法和一般方法很類似 , 但在
Java 中卻是被視為不同的元素 , 不能以呼叫其它方
法的方式呼叫建構方法。
 因此要呼叫其他版本的建構方法 , 必須使用 this 保
留字 , 例如。
this 保留字
this 保留字
 第 6 行的敘述 , 就是使用 this 呼叫其他版本建構方
法的方式 , 在 this 之後的小括號可以放入要傳遞給
其他版本建構方法的參數 , 編譯器就是透過這裡的參
數個數與型別來找尋適當的其他版本。
 為了類別特性的一致性 , 建議您可以多利用 this 保
留字 , 將重複的設定動作集中在適當的建構方法中 ,
並且在其他需要同樣建構方式的建構方法中呼叫該建
構方法 , 避免因為在不同的建構方法中的疏忽 , 而使
得產生的物件行為或是特性不一致。
▪ 請注意 , 在建構方法中 , 只有第一個敘述可使用 this
呼叫其他版本的建構方法 , 而不能先進行其他動作。
9-2 封裝與資訊隱藏
 學會建構方法的用法後 , 即可在建立物件時 , 一併完
成物件的初始化 , 不必再於 main() 方法中直接修改
物件的成員變數。
 但我們現在僅只是『不必』直接存取成員變數 , 對物
件導向程式設計方法 , 則是要求『不能』直接修改物
件的成員變數。
 以術語來說就是資訊隱藏 (Information Hiding), 亦即
類別外部 ( 例如 main() 方法 ) 不能看到、接觸到物
件內部的資訊 ( 屬性 ) 。
封裝與資訊隱藏
 那外部要如何得知或改變物件的屬性呢?
 那就必須透過類別公開給外部的方法 , 對應到生活中
實際接觸的物件也是如此 , 例如要讓車子前進 , 必須
透過車子提供給外部的油門;要轉彎 , 可使用方向盤
;而要讓行進中的車子停止 , 則要使用剎車。
 油門、方向盤、剎車就是車子提供給我們操作車子的
方法 , 使用這些方法 , 就會改變車子的狀態與屬性
( 速度、方向、位置、油量等等 ) 。
封裝與資訊隱藏
 因此當我們設計類別時 , 就必須提供必要的方法 , 讓
外部能正常操作物件。
 而透過這種程式設計方式 , 只要我們的類別有公開能
操作物件的方法 , 其他人就算完全不知道類別內部是
如何設計、運作 , 也可透過這些公開的介面來使用我
們所設計好的類別 , 達到程式碼重複使用、提高軟體
開發效率的目的。
封裝與資訊隱藏
 就好比大部份的駕駛人不會瞭解車子內部是如何設計
與運作 , 但只要會使用車子公開的油門、方向盤、剎
車 . . . 等介面 , 就會開車。
 而將類別的屬性、操作屬性的方法包裝在一起 , 只對
外公開必要的介面 , 即稱為封裝 (Encapsulation) 。
9-2-1 類別成員的存取控制
 為了讓外部不能任意存取封裝在類別內的屬性或方法
, 我們必須在類別之中 , 使用存取控制字符 (Access
Modifier) 來限制外部對類別成員的存取。
 以下是可以使用的存取限制字符。
類別成員的存取控制
 其中 protected 存取控制字符會在第 11 、 13 章做
進一步的說明 , 本章先說明 private 及 public 。
 private 存取控制字符 , 就如其英文字面含意一樣 ,
是指該成員變數是類別所私有 , 除了類別中的方法以
外 , 對於其他的類別來說 , 這個成員變數 ( 或方法 )
都好像看不到一樣 , 無法使用 , 例如。
類別成員的存取控制
類別成員的存取控制
類別成員的存取控制
 編譯時就會有錯誤訊息 , 表示 i 是 Test 類別中的
private 成員 , 所以不能在 Test 類別以外的地方存
取。
 只要把第 21 行刪除 , 程式就可以編譯並正確執行。
 也就是說 , 凡是被標示為 private 的成員 , 除非是透
過類別所定義的方法 , 否則就無法存取該成員。
 這正好就是這一節一開始所提到的資訊隱藏特性 , 在
上述的例子中 , main() 方法不能直接存取物件的成員
變數值 , 只能透過類別所提供的
show() 、 modifyMember() 方法來顯示或修改成員
變數 , 至於怎麼顯示或修改 , main() 方法則不需去瞭
解。
類別成員的存取控制
 如果沒有特別標示存取控制字符 , Java 就會採用預
設控制 (Default Access), 也就是只有同一個套件
(Package) 的類別可以存取此成員變數。
 我們會在第 13 章正式介紹套件 , 目前只需先記得 ,
如果編譯好的 .class 檔案都位於同一個資料夾 , 那
麼這些類別就會被視為是在同一個套件中。
 這也正是為什麼先前的範例程式全都沒有標示存取控
制字符 , 但在 main() 方法中可任意存取個別成員變
數的原因 , 因為同一個檔案中的類別在編譯後都會在
同一個資料夾下。
類別成員的存取控制
 另外 , 存取限制字符也可以應用在方法上 , 用來限制
哪些方法可以被外界呼叫 , 而哪些方法只是提供給類
別中的其他方法呼叫。
 在第 11 章還會針對存取限制字符做進一步的討論。
9-2-2 為成員變數撰寫存取方法
 為了實作資訊隱藏這個物件導向程式設計的基本觀念
, 在設計類別時 , 就要注意應盡量避免暴露類別內部
的實作細節 , 讓類別的使用者可不依賴內部實作細節
亦可撰寫程式。
 這樣的好處之一 , 即是若日後類別需變更內部的實作
方式 , 但只要它仍提供相同的操作方法 , 則使用者也
不必修改使用到該類別的程式。
為成員變數撰寫存取方法
 因此為了隱藏成員變數 , 我們就需適時地為成員變數
加上存取限制。一般而言 , 可使用下列的原則:
▪ 除非必要 , 最好所有成員變數都加上 private 存取限
制。
▪ 如果使用此類別的程式需要透過成員來完成某件事 ,
就由類別提供方法來完成。
為成員變數撰寫存取方法
▪ 如果需要修改或是取得成員的值 , 就提供專門存取成
員的方法。
通常用來取得成員值的方法會命名為 getXXX, 其中
XXX 就是成員變數的名稱;相對的 , 用來設定成員值
的方法就稱為 setXXX 。
這樣一來 , 可以將更改成員的動作侷限在此方法中 ,
往後對於除錯或是要為更改成員而引發的影響加上處
理工作時就會比較方便。
為成員變數撰寫存取方法
 相同的道理 , 對於類別中所定義的方法 , 加上存取限
制的通則如下:
▪ 如果是要提供給外界呼叫的方法 , 請明確的標示為
public 存取限制。像是剛剛所提到的 get 、 set 方法
, 就是最好的例子。
▪ 如果只是供類別中其他的方法呼叫的方法 , 請明確的
標示為 private 存取限制 , 以避免被類別外部的程式
呼叫。
▪ 對於建構方法 , 除非有特別的用途 , 否則應該都標示
為 public, 因為若是標示為 private, 則 new 運算子
就無法呼叫建構方法 , 因而不能設定物件的初始狀態
為成員變數撰寫存取方法
 以下面的程式為例:
為成員變數撰寫存取方法
為成員變數撰寫存取方法
 在程式中第 10 〜 13 行 , 就為 Test 類別的
private 成員 x 、 y 提供了一組存取的方法 , 並分別
取名為 getX 、 setX 與 getY 、 setY, 同時也特別
將這 2 組存取方法都標示為 public 存取限制。
 回頭看前一章的汽車類別範例 , 只要加上合適的建構
方法 , 並將成員變數設為 private, 就可讓它將資訊
隱藏起來 , 我們只能透過它所公開的方法來控制物件
。
為成員變數撰寫存取方法
為成員變數撰寫存取方法
為成員變數撰寫存取方法
為成員變數撰寫存取方法
 以這種方式撰寫程式時 , main() 方法的內容看起來會
比較簡潔 , 因為其中大多是直接呼叫類別所提供的方
法 , 我們也比較能看出 main() 方法是在做什麼事。
9-2-3 傳回成員物件的資訊
 透過前面幾個例子 , 相信大家都已對資訊隱藏有初步
的認識 , 原則就是將成員變數設為 private, 並提供
必要的公開方法。
 但如果類別的成員變數是另一個類別的物件 , 則在設
計與此成員物件相關的公開方法時 , 要注意是否要將
這個私有成員物件 , 也公開到外部。
 舉例來說 , 在平面幾何中 , 一個圓的可以由一個圓心
座標和半徑來定義。
 因此我們可以先設計一個代表座標點的類別 Point,
然後再於圓的類別中用 Point 的物件代表圓心座標 ,
例如。
傳回成員物件的資訊
傳回成員物件的資訊
 在 Circle 類別中的 getP() 方法 , 其用途是讓外界
取得圓心座標 , 但如果直接傳回私有成員變數 p 的
參照 , 那麼外界就可取得此物件的參照 , 並透過此參
照呼叫 Point 類別的 setX() 、 setY() 方法。
 如此一來就變成外界可直接修改私有成員物件了 , 請
參考以下的例子。
傳回成員物件的資訊
傳回成員物件的資訊
傳回成員物件的資訊
傳回成員物件的資訊
 在第 20 行為 Circle 類別定義了一個取得圓心座標
的 getP() 方法 , 此方法直接將成員變數 p 傳回 ,
也就是傳回圓心物件的參照。
 因此當 main() 方法在第 36 行用 getP() 方法取得
圓心後 , 可在第 37 行用它呼叫 Point 類別的
setX() 方法來變更 X 軸座標。
 由執行結果也可看到圓心的 X 軸座標的確被更改了
。
傳回成員物件的資訊
 雖然這樣改變圓心座標的方式看似合理 , 但對 Circle
類別而言 , 卻失去『資訊隱藏』的特性 , 因為外界不
需透過它 , 即可任意變更其圓心座標。
 雖然成員變數 p 確實是 private, 但因為 getP() 方
法是將其參照傳回 , 所以外界即可透過此參照直接存
取到私有的物件。
 如果要保護 Circle 類別的內容 , 則可修改 getP()
方法 , 讓它變成傳回另一個座標值相同的 Point 物
件 , 而非傳回私有的 Point 物件參照。
傳回成員物件的資訊
 如此一來外界仍能取得一個代表圓心座標的 Point
物件 , 但該物件並非 Circle 類別的成員 , 因而可達
到『資訊隱藏』的目的。修改後的程式如下:
傳回成員物件的資訊
傳回成員物件的資訊
 這個範例與前一個範例有 2 個主要不同之處:
1. 第 15 〜 18 行為 Point 類別定義了另一個建建構
方法 , 此建構方法是用現有的點物件為參數 , 並複製
參數物件的座標值給新物件。
2. 第 25 〜 27 行的 getP() 方法 , 改成傳回一個新建
立的 Point 物件 , 而非私有的成員變數 p, 但建立
新物件時則是以 p 為參數 , 所以傳回的物件之座標
會與圓心相同。
傳回成員物件的資訊
 經過上述的修改後 , 在 main() 中取得並修改圓心的
座標時 , 即不會動到 Circle 物件實際的圓心。
 由執行結果可發現 , 程式最後顯示圓的資訊時 , 其圓
心座標並未被修改。
 這兩個範例程式中 , 都為類別定義了一個 toString()
方法 , 這個方法會將物件的資訊以字串的形式傳回 ,
這種設計方式 , 讓我們需要輸出物件資訊時 , 可以有
較彈性的用法 , 因為我們可利用 "+" 運算子將多個
字串組合在一起。
▪ 在下一章即會進一步介紹 String 字串類別的用法。
9-2-4 JavaBean 的命名標準
 JavaBean 是一種由 Java 語言所製作成的元件
(Component), 可以安裝到 Java 的整合發環境中
( 例如 NetBeans 或 Eclipse), 讓設計師很輕鬆地將
之當成元件來使用其功能。
 雖然本書不會介紹此進階功能 , 但建議讀者都能遵循
JavaBean 的命名標準 , 讓您的程式更具有可讀性及
通用性。
▪ 如何以 JavaBean 的命名標準來為方法命名 , 也是
SCJP 的考試範圍喔 ( 但 JavaBean 的設計與使用則
不會考 ) !
JavaBean 的命名標準
 JavaBean 將成員變數稱為欄位 (field), 這些欄位必
須宣告為 private, 以符合封裝的要求。
 類別中屬性與方法的命名標準和前面章節所介紹的相
同 , 就是開頭要小寫且後面的每個單字開頭要大寫 ,
例如 name 、 isOpened 、 readFileData 。
 此外 , 在撰寫存取欄位的 Getter ( 取值方法 ) 及
Setter ( 設值方法 ) 時 , 必須遵循一套特殊的規則。
JavaBean 的命名標準
 另外 , 還有一種支援事件處理的 Listener ( 監聽方
法 ) 也有特殊規則 , 底下就分別介紹這 3 種方法的
命名標準:
▪ Getter :用來讀取某個欄位 ( 成員變數 ) 的值 , 其宣
告的格式為:
其中存取控制必須為 public, 而 type 為要讀取欄位
的型別。
Xxx 要首字大寫 , 但不一定要和欄位名稱相同 , 只要
具備可讀性即可 , 例如 public int getSize() 、 public
float getValue() 。
JavaBean 的命名標準
此外 , 如果欄位的型別為 boolean, 那麼也可將 get
改為 is :

例如 isReady() 和 getReady() 都是正確的命名方式
。
JavaBean 的命名標準
▪ Setter :用來設定某個欄位 ( 成員變數 ) 的值 , 其宣
告的格式為:

Setter 和 Getter 類似 , 但傳回值必須為 void, 而且
要接受一個參數 , 其型別和要設定欄位的型別相同。
例如 public void setSize(int x) 、 public void
setValue(float f) 。
JavaBean 的命名標準
▪ Listener :用來加入 (add) 或移除 (remove) 某個事
件的監聽方法 , 格式如下:

▪ 開頭必須為 public void, 方法的名稱則必須為 add 或
remove, 後面接著事件監聽的類別名稱 XxxListener,
並接收一個事件監聽類別的參數。例如:
9-3 static 共享成員變數
 前面的類別範例所建立的物件 , 都能擁有個自己的成
員變數 , 以表現物件屬性間的差異。
 但在某些情況下 , 我們可能會想讓所有物件的某個屬
性都是相同的 , 此時就可使用 static 共享成員變數
來表現這個物件的共通屬性。
static 共享成員變數

 以我們示範過的汽車類別為例 , 假如該類別代表的是
某一款特定的車型 , 所有物件代表同型車的多個個體。
載油量當然會隨車子所加的油量、行駛的里程而隨時
變動;但耗油率我們可能想將之設為固定值 , 即所有
物件的耗油率都相同。
 此時若單只是在建構物件時 , 將耗油率設為相同的數
值 , 並不方便 , 也不安全 , 因為如果寫程式時不小心
寫錯了 , 就會造成耗油率不一致等問題。
 因此 Java 就提供 static 的成員變數 , 來解決這個
問題。
9-3-1 static 存取控制
 當我們將類別的成員變數加上 static 存取控制字符 ,
就表示所有屬於此類別的物件 , 都會共享這個成員 ,
而非每一個物件擁有自己的一份成員。舉例來說:
static 存取控制
static 存取控制
 在程式 18 〜 20 行雖然分別為物件的成員變數 y
設定不同的值 , 但由於該成員變數為 static , 所以其
實這 3 個物件的成員變數 y 是同一份 , 每次設定值
時 , 都是設定同一個 y, 因此最後一次呼叫建構方法
時將之設為 60 之後 , 不論是透過 a 、 b 、 c 參照
來取得成員變數 y 的值 , 都是 60 了。
 反之 , 成員變數 x 則因為不是 static, 所以個別物件
都享有自己的一份。
9-3-2 使用類別名稱存取 static 成員變數
 static 成員變數除了可用如同一般成員變數的方式存
取外 , 也可以透過類別名稱存取之。
 以剛剛的 Test 類別 , 我們可以用如下的方式存取成
員變數 y :
static 存取控制

 在第 21 行以『類別名稱 . 成員變數名稱』的方式即
存取到 y, 並將它設為 100, 所以之後顯示物件內容
時 , 其 y 值都是 100 。
static 存取控制
 此外 , 我們甚至可在未建立物件的情況下 , 也能使用
類別的 static 成員變數:
static 存取控制
static 存取控制
 在這個範例中 , Test 類別的建構方法只會設定成員變
數 x 的值。
 而第 17 行則在未產生任何物件之前即存取 static
成員變數 y, 並設妥其值 , 所以之後的建構方法雖未
設定 y 的值 , 但由執行結果可看到各物件的 y 值都
是 100 。
9-3-3 static 初始區塊
 由於 static 成員變數的共享特性 , 通常不會在建構
方法中設定其初值 , 因此 static 成員變數要不就是
在宣告的同時直接設定初值 , 要不就是另外單獨設定
。
 為了避免寫程式時忘了設定 static 成員變數 , Java
還提供了 static 初始區塊 (Static Initializer), 可以
確保在產生物件之前 , 設定 static 成員。
 其用法就是在類別的定義中 , 加入一個以 static 保
留字為首的大括號區塊 , 並在此區塊中加入初始化
static 成員變數的敘述 , 例如。
static 初始區塊
static 初始區塊
static 初始區塊
 在類別中的 static 區塊 , 會在程式使用到該類別之
前執行。
 以上列程式為例 , 第 5 〜 7 行就是 static 初始區
塊 , 它會在程式中第一次使用到 Test 類別 ( 即第
23 行 ) 之前執行 , 因此第 23 行顯示的結果就是執
行過 static 初始區塊後的成員 y 的值 100 。
static 初始區塊
 由於 static 成員變數是由同一類別的所有物件所共
享 , 且不需先產生物件 , 即可以透過類別名稱存取 ,
因此又稱為類別變數 (Class Variable) 。
 相對的 , 非 static 的成員變數因為是每個物件各自
擁有一份 , 需建立物件後才能使用 , 因此稱為實體變
數 (Instance Variable) 。
▪ 建立物件又可稱為建立一個實體 (Instance) 。
9-3-4 static 方法
 static 除了可以使用在成員變數上以外 , 也可以應用
在方法上。
 一個標示有 static 存取控制的方法除了可以透過所
屬類別的物件呼叫以外 , 也和 static 成員變數一樣 ,
可以在沒有產生任何物件的情況下透過類別名稱呼叫
, 例如。
static 方法
static 方法
 由於 static 成員變數及方法不需產生物件即可使用
的特性 , 因此可以用來提供一組相關聯的工具方法或
是常數值。
 像是 Java 類別庫中的 Math 類別 , 就提供許多與
數學相關的 static 運算方法 ( 像是算次方、取亂數
、三角函數等等 ) 以及 static 常數值 ( 例如圓周
率)。
static 方法
 請特別注意 , 在 static 區塊或方法之中 , 不能用到
任何非 static 的成員變數以及方法 , 也不能使用
this 保留字。
 這其實很容易理解 , 因為非 static 的成員變數和方
法是跟隨物件而生 , 而 static 區塊或方法可以在沒
有產生任何物件之前使用 , 此時因為沒有產生物件 ,
自然就不會配置有非 static 的成員變數 , 而 this 也
沒有物件可指。
解開 main() 方法之謎
 從這裡的解說就可以將 main() 方法的神秘面紗揭開
了 , 原來 main() 方法只是一個 public static 的方法
, 而且不會傳回任何值。
9-3-5 final 存取控制
 static 成員變數常常用來提供給同一類別的所有物件
一份一致的資料 , 供所有的物件共用。
 為達成此目的 , 還需要有一種方法 , 可以在設定好
static 成員變數的初值後就不能更改 , 否則各別物件
都隨意去更動 static 成員變數的值 , 就不是一份一
致的資料了。
 為達到此目的 , 可以搭配第 3 章介紹過的 final 字
符 , 限制特定的 static 成員變數在設定過初值之後
就不允許更動 , 例如。
final 存取控制
final 存取控制
 第 2 行中宣告了 x 是 final, 所以第 9 行的設定動
作在編譯時就會被視為錯誤。
 要特別注意的是 , 一旦宣告了成員變數為 final 後 ,
如果是 static 成員變數 , 那麼就必須要在宣告同時
或是在 static 初始區塊中設定初值。
 如果是非 static 成員變數 , 就必須在宣告同時或是
在建構方法中設定初值 , 否則都會被視為是錯誤。
9-3-6 靜態變數與實體變數的預設值
 凡是宣告在方法之外的變數 ( 靜態變數或實體變數 ),
除非宣告為 final 變數 ( 例如前一個範例 , 就必須設
定初值 ), 否則都會有預設值 , 如下表所示:
靜態變數與實體變數的預設值
 其中要特別注意物件參照 ( 類別 ) 的預設值為 null,
例如:
靜態變數與實體變數的預設值
 以上程式的最後一行 , 就是因為 Test.z 的值為 null,
因此後面不可再用句點來存取其內的成員了。
 此時我們也可加一個 i f 判斷式來避免此問題:
靜態變數與實體變數的預設值
 從另一方面來看 , 凡是宣告在方法之內的變數 ( 稱為
區域變數 ) , 則不會有預設值 , 我們必須先設定變數
的值 , 然後才能讀取其內容 , 否則編譯器會視為錯誤
, 例如。
靜態變數與實體變數的預設值
 在以上程式中 , 請注意陣列變數 (b) 在用 new 初始
化 ( 配置實體元素 ) 之後 , 其內的元素也會自動指定
初值 ( 因為陣列也是一種物件 ), 這在第 7 章已介紹
過了。
▪ 凡是以 new 配置記憶空間的物件或陣列 , 其內的成
員變數或陣列元素都會具有預設值。
 9-A 提供輔助工具的類別
 9-B 善用多重定義
1. Given:
What is the result?
A. 5 4 3 2
B. 5 4 4 3
C. 5 5 4 3
D. 5 5 4 4
E. Compilation fails.
2. Which statements concerning following code are true?
(Choose two or three)
A. This class is fully encapsulated.
B. B. The variables break the encapsulation of class.
C. C. The methods break the encapsulation of class
D. D. All methods are following the JavaBean standard.
E. E. Some methods are not following the JavaBean
standard.
3. Which of following methods are valid constructor for class
Note? (Choose all that apply)
A. public Note() { ... }
B. public void Note() { ... }
C. private Note() { ... }
D. public static Note() { ... }
E. Note() { ... }
F. final Note() { ... }
4. Given following Java code:
What is the result?
A. C6 C1 C2 C3 C4 C5
B. C6 C1 C3 C4 C2 C5
C. C6 C1 C3 C4 C5 C2
D. C6 C4 C3 C1 C2 C5
E. C6 C4 C3 C1 C5 C2
5. A JavaBean Class has following field:

Which method declaration follows JavaBean standard?
(Choose all that apply)
A. public void getVisible()
B. public boolean getVisible()
C. private boolean isVisible()
D. public boolean isVisible()
E. public boolean canVisible()
F. private boolean canVisible()
6. Given:

Which four statements are true? (Choose four)
A. fun1() can directly modify field i.
B. fun1() can directly modify field j.
C. fun2() can directly modify field i.
D. fun1() can directly call fun2().
E. fun2() can directly call fun1().
F. StaticQuiz.fun1() is a valid invocation outside StaticQuiz
class.
G. StaticQuiz.fun2() is a valid invocation outside StaticQuiz
class.
7. Given:
How many objects are created in main()?
How many object is available for Garbage Collection at line 13?
A. 2 objects are created.
B. 4 objects are created.
C. 5 objects are created.
D. 1 object is avaible for Garbage Collection.
E. 2 object is avaible for Garbage Collection.
F. 3 object is avaible for Garbage Collection.
8. What is the result of following program:
A.
B.
C.
D.
E.

Counter=2
Compilation fails at line 3.
Compilation fails at line 4.
Compilation fails at line 9.
Compilation fails at line 10. F. Runtime error.
9. Given:

What is the result?
A. 300 200
B. 200 300
D. 250 300
E. 250 250

C. 300 250
10.Given:

How many objects are available for Garbage Collection at line
14?

A. 0

B. 1

C. 2

D. 3

E. 4
SCJP ch09

Mais conteúdo relacionado

Mais procurados

Java面试知识
Java面试知识Java面试知识
Java面试知识yiditushe
 
lwdba – 開放原始碼的輕量級資料庫存取程式庫
lwdba – 開放原始碼的輕量級資料庫存取程式庫lwdba – 開放原始碼的輕量級資料庫存取程式庫
lwdba – 開放原始碼的輕量級資料庫存取程式庫建興 王
 
Spring入门纲要
Spring入门纲要Spring入门纲要
Spring入门纲要yiditushe
 
Jsp面试知识
Jsp面试知识Jsp面试知识
Jsp面试知识yiditushe
 
Java相关基础知识
Java相关基础知识Java相关基础知识
Java相关基础知识yiditushe
 
Struts Mitac(1)
Struts Mitac(1)Struts Mitac(1)
Struts Mitac(1)wangjiaz
 
Moodle 项目帮助手册:程序编写准则
Moodle 项目帮助手册:程序编写准则Moodle 项目帮助手册:程序编写准则
Moodle 项目帮助手册:程序编写准则YUCHENG HU
 
数据库原理第三章
数据库原理第三章数据库原理第三章
数据库原理第三章strun
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非Tony Deng
 
中远公司 Java培训资料
中远公司  Java培训资料中远公司  Java培训资料
中远公司 Java培训资料yiditushe
 
6, OCP - oracle security
6, OCP - oracle security6, OCP - oracle security
6, OCP - oracle securityted-xu
 

Mais procurados (20)

SCJP ch02
SCJP ch02SCJP ch02
SCJP ch02
 
Java面试知识
Java面试知识Java面试知识
Java面试知识
 
SCJP ch13
SCJP ch13SCJP ch13
SCJP ch13
 
Java物件導向
Java物件導向Java物件導向
Java物件導向
 
Refactoring
RefactoringRefactoring
Refactoring
 
SCJP ch11
SCJP ch11SCJP ch11
SCJP ch11
 
lwdba – 開放原始碼的輕量級資料庫存取程式庫
lwdba – 開放原始碼的輕量級資料庫存取程式庫lwdba – 開放原始碼的輕量級資料庫存取程式庫
lwdba – 開放原始碼的輕量級資料庫存取程式庫
 
Refactoring 重构
Refactoring 重构Refactoring 重构
Refactoring 重构
 
Spring入门纲要
Spring入门纲要Spring入门纲要
Spring入门纲要
 
Jsp面试知识
Jsp面试知识Jsp面试知识
Jsp面试知识
 
Java相关基础知识
Java相关基础知识Java相关基础知识
Java相关基础知识
 
SCJP ch08
SCJP ch08SCJP ch08
SCJP ch08
 
Struts Mitac(1)
Struts Mitac(1)Struts Mitac(1)
Struts Mitac(1)
 
Moodle 项目帮助手册:程序编写准则
Moodle 项目帮助手册:程序编写准则Moodle 项目帮助手册:程序编写准则
Moodle 项目帮助手册:程序编写准则
 
数据库原理第三章
数据库原理第三章数据库原理第三章
数据库原理第三章
 
Javascript之昨是今非
Javascript之昨是今非Javascript之昨是今非
Javascript之昨是今非
 
Hibernate教程
Hibernate教程Hibernate教程
Hibernate教程
 
中远公司 Java培训资料
中远公司  Java培训资料中远公司  Java培训资料
中远公司 Java培训资料
 
6, OCP - oracle security
6, OCP - oracle security6, OCP - oracle security
6, OCP - oracle security
 
SCJP ch15
SCJP ch15SCJP ch15
SCJP ch15
 

Semelhante a SCJP ch09

Using Java reflection to break  encapsulation
Using Java reflection to break  encapsulationUsing Java reflection to break  encapsulation
Using Java reflection to break  encapsulation祺傑 林
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程appollo0312
 
000 北京圣思园教育科技有限公司第一期面授培训大纲
000 北京圣思园教育科技有限公司第一期面授培训大纲000 北京圣思园教育科技有限公司第一期面授培训大纲
000 北京圣思园教育科技有限公司第一期面授培训大纲ArBing Xie
 
Django development
Django developmentDjango development
Django developmentloveyudu
 
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註Justin Lin
 
網站設計100步
網站設計100步網站設計100步
網站設計100步evercislide
 
Model 設定與 Seeding
Model 設定與 SeedingModel 設定與 Seeding
Model 設定與 SeedingShengyou Fan
 
Backbone js and requirejs
Backbone js and requirejsBackbone js and requirejs
Backbone js and requirejsChi-wen Sun
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Wade Huang
 
Kissy design
Kissy designKissy design
Kissy designyiming he
 
Abap oo
Abap ooAbap oo
Abap oovernoo
 

Semelhante a SCJP ch09 (20)

Using Java reflection to break  encapsulation
Using Java reflection to break  encapsulationUsing Java reflection to break  encapsulation
Using Java reflection to break  encapsulation
 
SCJP ch17
SCJP ch17SCJP ch17
SCJP ch17
 
SCJP ch07
SCJP ch07SCJP ch07
SCJP ch07
 
SCJP ch12
SCJP ch12SCJP ch12
SCJP ch12
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
000 北京圣思园教育科技有限公司第一期面授培训大纲
000 北京圣思园教育科技有限公司第一期面授培训大纲000 北京圣思园教育科技有限公司第一期面授培训大纲
000 北京圣思园教育科技有限公司第一期面授培训大纲
 
Django development
Django developmentDjango development
Django development
 
111
111111
111
 
111
111111
111
 
111
111111
111
 
111
111111
111
 
111
111111
111
 
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
Java SE 7 技術手冊投影片第 16 章 - 自訂泛型、列舉與標註
 
網站設計100步
網站設計100步網站設計100步
網站設計100步
 
Model 設定與 Seeding
Model 設定與 SeedingModel 設定與 Seeding
Model 設定與 Seeding
 
Backbone js and requirejs
Backbone js and requirejsBackbone js and requirejs
Backbone js and requirejs
 
Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有Asp.net mvc網站的從無到有
Asp.net mvc網站的從無到有
 
Kissy design
Kissy designKissy design
Kissy design
 
Abap oo
Abap ooAbap oo
Abap oo
 

Mais de r82093403

Ciw going mobile
Ciw going mobileCiw going mobile
Ciw going mobiler82093403
 
The lpic 2 exam prep
The lpic 2 exam prepThe lpic 2 exam prep
The lpic 2 exam prepr82093403
 
Exploration network chapter3
Exploration network chapter3Exploration network chapter3
Exploration network chapter3r82093403
 
Exploration network chapter7
Exploration network chapter7Exploration network chapter7
Exploration network chapter7r82093403
 
Exploration network chapter11
Exploration network chapter11Exploration network chapter11
Exploration network chapter11r82093403
 
Exploration network chapter10
Exploration network chapter10Exploration network chapter10
Exploration network chapter10r82093403
 
Exploration network chapter9
Exploration network chapter9Exploration network chapter9
Exploration network chapter9r82093403
 
Exploration network chapter6
Exploration network chapter6Exploration network chapter6
Exploration network chapter6r82093403
 
Exploration network chapter4
Exploration network chapter4Exploration network chapter4
Exploration network chapter4r82093403
 
Exploration network chapter2
Exploration network chapter2Exploration network chapter2
Exploration network chapter2r82093403
 
Exploration network chapter1
Exploration network chapter1Exploration network chapter1
Exploration network chapter1r82093403
 

Mais de r82093403 (20)

Ciw going mobile
Ciw going mobileCiw going mobile
Ciw going mobile
 
The lpic 2 exam prep
The lpic 2 exam prepThe lpic 2 exam prep
The lpic 2 exam prep
 
SCJP ch18
SCJP ch18SCJP ch18
SCJP ch18
 
SCJP ch16
SCJP ch16SCJP ch16
SCJP ch16
 
SCJP ch14
SCJP ch14SCJP ch14
SCJP ch14
 
SCJP ch10
SCJP ch10SCJP ch10
SCJP ch10
 
SCJP ch06
SCJP ch06SCJP ch06
SCJP ch06
 
SCJP ch05
SCJP ch05SCJP ch05
SCJP ch05
 
SCJP ch04
SCJP ch04SCJP ch04
SCJP ch04
 
SCJP ch03
SCJP ch03SCJP ch03
SCJP ch03
 
SCJP ch01
SCJP ch01SCJP ch01
SCJP ch01
 
Exploration network chapter3
Exploration network chapter3Exploration network chapter3
Exploration network chapter3
 
Exploration network chapter7
Exploration network chapter7Exploration network chapter7
Exploration network chapter7
 
Exploration network chapter11
Exploration network chapter11Exploration network chapter11
Exploration network chapter11
 
Exploration network chapter10
Exploration network chapter10Exploration network chapter10
Exploration network chapter10
 
Exploration network chapter9
Exploration network chapter9Exploration network chapter9
Exploration network chapter9
 
Exploration network chapter6
Exploration network chapter6Exploration network chapter6
Exploration network chapter6
 
Exploration network chapter4
Exploration network chapter4Exploration network chapter4
Exploration network chapter4
 
Exploration network chapter2
Exploration network chapter2Exploration network chapter2
Exploration network chapter2
 
Exploration network chapter1
Exploration network chapter1Exploration network chapter1
Exploration network chapter1
 

SCJP ch09

  • 1. 第 9 章 物件的建構 本投影片(下稱教用資源)僅授權給採用教用資源相關之旗標書籍為教科書之授課老師(下稱老師)專用,老 師為教學使用之目的,得摘錄、編輯、重製教用資源(但使用量不得超過各該教用資源內容之 80% )以製作為 輔助教學之教學投影片,並於授課時搭配旗標書籍公開播放,但不得為網際網路公開傳輸之遠距教學、網路教 學等之使用;除此之外,老師不得再授權予任何第三人使用,並不得將依此授權所製作之教學投影片之相關著 作物移作他用。 著作權所有 © 旗標出版股份有限公司
  • 3. 前言  前一章學習了定義類別、使用物件的基本方式。但由 上一章所學 , 在程式中使用物件時仍相當不便 , 感覺 也相當不『物件導向』。  以前一章範例程式中所用的汽車類別為例 , 每次建立 物件後 , 都還要在 main() 方法中另行設定物件的成 員變數的值。
  • 5. 前言  如果可以將建立物件與設定物件狀態的動作結合在一 起 , 會有以下優點: ▪ 避免忘記設定物件初始狀態 , 這種錯誤看起來雖然是小事 , 但往往在程式出錯時也最容易忽略。由於編譯器無法猜測 物件在產生後是否需要進行任何初始化的動作 , 因此無法 像是警告您變數尚未設定初值的方式提出警示。 ▪ 更接近自然界的物件。舉例來說 , 小嬰孩必定在出生前就 決定了膚色與髮色 , 而不會是先出生 , 然後才顯現膚色或 是髮色;相同的道理 , 舞台劇上場的演員也不會先出場 , 然後請觀眾等一下 , 在台上上妝之後才開始演出。既然如 此 , 程式中的各個物件也應該在產生的同時就設定好初始 狀態 , 直接參與程式的執行。
  • 6. 前言  為了解決上述的問題 , Java 這一類物件導向的程式 語言便提供一個特別的機制 , 來幫物件設定初始狀態 , 而這也就是本章的主題。
  • 7. 9-1 建構方法 (Constructor)  建構方法就是物件導向程式語言對於物件初始化的解 決方案。  顧名思義 , 建構方法是一個方法 (method), 比較特 別的是:它是在建立物件時由系統自動呼叫 , 以建構 物件初始的狀態 , 因此名之為建構方法。  也因為在物件產生時會自動呼叫建構方法 , 因此使用 new 運算子時 , 才必須在類別的名稱之後加上一對 小括號 , 這對小括號的意義就是呼叫建構方法。
  • 8. 9-1-1 預設建構方法 (Default Constructor)  建構方法的名稱與類別名稱相同 , 如果類別之中並未 定義任何建構方法 , 則 Java 編譯器會自動幫類別定 義一個預設建構方法 , 例如:
  • 9. 預設建構方法 (Default Constructor)  在上面這個例子中 , Test 類別就沒有定義任何的建構 方法 , 因此 Java 編譯器便會自動定義一個預設的建 構方法 , 此時就如同以下的程式:
  • 10. 預設建構方法 (Default Constructor)  第 5 〜 6 行就是一個建構方法 , 但這個建構方法什 麼事情都沒有做 , 單純只是為了類別必須定義有建構 方法而存在。  也正因為如此 , 如果類別在產生物件的時候並不需要 進行任何初始化的動作 , 撰寫時就可以省略定義建構 方法 , 讓 Java 編譯器自動替我們產生。
  • 11. 9-1-2 自行定義建構方法  如果需要對新建立的物件進行任何初始化設定 , 那麼 就可以自行定義建構方法。  定義建構方法時除了要依循一般方法的定義規則外 , 還有以下幾點需要注意: ▪ 建構方法不能傳回任何值 , 因此不需也不能註明傳回 值 型別 , 連 void 也不可加上 , 如果加上傳回型別 , 反而會造成編譯錯誤。 ▪ 建構方法一定要和類別同名 , 而不可使用其他名稱。
  • 14. 無參數的建構方法  在程式第 14 行一樣是用 new 運算子建立物件 , 由 於 Java 會自動呼叫第 5 〜 8 行的建構方法 , 所以 成員變數 x 與 y 都被設為指定的值 , 並不需要在產 生物件之後另外指定。
  • 15. 具有參數的建構方法  建構方法也可接受參數 , 讓物件的建構時更具彈性。  建構方法若能接受參數 , 在建立物件時 , 就可以透過 跟隨在 new 運算子以及類別名稱之後的那一對小括 號傳入參數。例如:
  • 17. 具有參數的建構方法  要特別注意的是 , 一旦定義了建構方法之後 , 使用 new 運算子產生物件時就必須依據建構方法的定義 , 傳入相同數量以及型別的參數 , 就像是呼叫一般的方 法一樣 , 否則編譯時就會產生錯誤 , 例如:
  • 19. 具有參數的建構方法  編譯後的錯誤訊息告訴我們 , 編譯器找不到僅需要單 一個整數的建構方法。
  • 20. 9-1-3 建構方法的多重定義 (Overloading)  建構方法也和一般的方法一樣 , 可以使用多重定義的 方式 , 定義多種版本的建構方法 , 以便能夠依據不同 的場合 , 為新產生的物件進行最適當的初始設定。  編譯器會依據所傳入參數的個數以及資料型別 , 選擇 符合的建構方法 , 就像是編譯器選擇多重定義的一般 方法時一樣。  舉例來說 , 底下的類別就同時定義有多個版本的建構 方法:
  • 23. 建構方法的多重定義 (Overloading)  在此範例中 , Test 類別擁有 3 種版本的建構方法 , 如此就可以依據需要 , 使用適當的建構方法。
  • 24. 建構方法的多重定義 (Overloading)  有一點需要特別注意:當我們為類別定義需要參數的 建構方法時 , Java 編譯器就不會替我們建立無參數 的預設建構方法 , 因此這時候最好也自行為類別加上 一個不需參數的建構方法。  因為當程式產生物件時 , 未必每次都需要將物件設定 為特定狀態 , 此時這個不需參數的建構方法就可以提 供一種預設狀 態給物件 , 撰寫程式時就可以享有一定 程度的方便性。  因此 , 建議在為類別設計建構方法時 , 先定義一個不 具參數的建構方法 , 可以將物件設定為預設的狀態。 接著 , 再根據不同的情況 , 定義特殊的版本。
  • 25. 9-1-4 this 保留字  由於建構方法主要的用途是設定物件的初始狀態 , 傳 入的參數大多與類別的成員變數相關 , 因此在為這些 參數命名時通常都會和成員變數相同 , 這時就和一般 的方法一樣 , 參數的名稱會遮蔽掉 (Shadowing) 成 員變數。  如果需要存取成員時 , 就可以使用上一章介紹過的 this 保留字 , 以表示目前執行此方法的物件 , 例如 。
  • 27. this 保留字  除了在參數名稱與成員名稱相同的情況派上用場外 , this 保留字還有一個很大的妙用。  如果在建構方法中所需要進行的設定 , 有一部份在另 外一個版本的建構方法中完全重複 , 而想要在直接呼 叫該版本的建構方法時 , 並不能直接使用類別名稱呼 叫該建構方法。
  • 30. this 保留字  在第 6 行中 , 本來想要利用另一個只需單一參數的 建構方法設定成員變數 x 的值 , 但是從編譯後的錯 誤訊息說明了編譯器找不到一個叫做 Test() 的方法 。  換句話說 , 雖然建構方法和一般方法很類似 , 但在 Java 中卻是被視為不同的元素 , 不能以呼叫其它方 法的方式呼叫建構方法。  因此要呼叫其他版本的建構方法 , 必須使用 this 保 留字 , 例如。
  • 32. this 保留字  第 6 行的敘述 , 就是使用 this 呼叫其他版本建構方 法的方式 , 在 this 之後的小括號可以放入要傳遞給 其他版本建構方法的參數 , 編譯器就是透過這裡的參 數個數與型別來找尋適當的其他版本。  為了類別特性的一致性 , 建議您可以多利用 this 保 留字 , 將重複的設定動作集中在適當的建構方法中 , 並且在其他需要同樣建構方式的建構方法中呼叫該建 構方法 , 避免因為在不同的建構方法中的疏忽 , 而使 得產生的物件行為或是特性不一致。 ▪ 請注意 , 在建構方法中 , 只有第一個敘述可使用 this 呼叫其他版本的建構方法 , 而不能先進行其他動作。
  • 33. 9-2 封裝與資訊隱藏  學會建構方法的用法後 , 即可在建立物件時 , 一併完 成物件的初始化 , 不必再於 main() 方法中直接修改 物件的成員變數。  但我們現在僅只是『不必』直接存取成員變數 , 對物 件導向程式設計方法 , 則是要求『不能』直接修改物 件的成員變數。  以術語來說就是資訊隱藏 (Information Hiding), 亦即 類別外部 ( 例如 main() 方法 ) 不能看到、接觸到物 件內部的資訊 ( 屬性 ) 。
  • 34. 封裝與資訊隱藏  那外部要如何得知或改變物件的屬性呢?  那就必須透過類別公開給外部的方法 , 對應到生活中 實際接觸的物件也是如此 , 例如要讓車子前進 , 必須 透過車子提供給外部的油門;要轉彎 , 可使用方向盤 ;而要讓行進中的車子停止 , 則要使用剎車。  油門、方向盤、剎車就是車子提供給我們操作車子的 方法 , 使用這些方法 , 就會改變車子的狀態與屬性 ( 速度、方向、位置、油量等等 ) 。
  • 35. 封裝與資訊隱藏  因此當我們設計類別時 , 就必須提供必要的方法 , 讓 外部能正常操作物件。  而透過這種程式設計方式 , 只要我們的類別有公開能 操作物件的方法 , 其他人就算完全不知道類別內部是 如何設計、運作 , 也可透過這些公開的介面來使用我 們所設計好的類別 , 達到程式碼重複使用、提高軟體 開發效率的目的。
  • 36. 封裝與資訊隱藏  就好比大部份的駕駛人不會瞭解車子內部是如何設計 與運作 , 但只要會使用車子公開的油門、方向盤、剎 車 . . . 等介面 , 就會開車。  而將類別的屬性、操作屬性的方法包裝在一起 , 只對 外公開必要的介面 , 即稱為封裝 (Encapsulation) 。
  • 37. 9-2-1 類別成員的存取控制  為了讓外部不能任意存取封裝在類別內的屬性或方法 , 我們必須在類別之中 , 使用存取控制字符 (Access Modifier) 來限制外部對類別成員的存取。  以下是可以使用的存取限制字符。
  • 38. 類別成員的存取控制  其中 protected 存取控制字符會在第 11 、 13 章做 進一步的說明 , 本章先說明 private 及 public 。  private 存取控制字符 , 就如其英文字面含意一樣 , 是指該成員變數是類別所私有 , 除了類別中的方法以 外 , 對於其他的類別來說 , 這個成員變數 ( 或方法 ) 都好像看不到一樣 , 無法使用 , 例如。
  • 41. 類別成員的存取控制  編譯時就會有錯誤訊息 , 表示 i 是 Test 類別中的 private 成員 , 所以不能在 Test 類別以外的地方存 取。  只要把第 21 行刪除 , 程式就可以編譯並正確執行。  也就是說 , 凡是被標示為 private 的成員 , 除非是透 過類別所定義的方法 , 否則就無法存取該成員。  這正好就是這一節一開始所提到的資訊隱藏特性 , 在 上述的例子中 , main() 方法不能直接存取物件的成員 變數值 , 只能透過類別所提供的 show() 、 modifyMember() 方法來顯示或修改成員 變數 , 至於怎麼顯示或修改 , main() 方法則不需去瞭 解。
  • 42. 類別成員的存取控制  如果沒有特別標示存取控制字符 , Java 就會採用預 設控制 (Default Access), 也就是只有同一個套件 (Package) 的類別可以存取此成員變數。  我們會在第 13 章正式介紹套件 , 目前只需先記得 , 如果編譯好的 .class 檔案都位於同一個資料夾 , 那 麼這些類別就會被視為是在同一個套件中。  這也正是為什麼先前的範例程式全都沒有標示存取控 制字符 , 但在 main() 方法中可任意存取個別成員變 數的原因 , 因為同一個檔案中的類別在編譯後都會在 同一個資料夾下。
  • 43. 類別成員的存取控制  另外 , 存取限制字符也可以應用在方法上 , 用來限制 哪些方法可以被外界呼叫 , 而哪些方法只是提供給類 別中的其他方法呼叫。  在第 11 章還會針對存取限制字符做進一步的討論。
  • 44. 9-2-2 為成員變數撰寫存取方法  為了實作資訊隱藏這個物件導向程式設計的基本觀念 , 在設計類別時 , 就要注意應盡量避免暴露類別內部 的實作細節 , 讓類別的使用者可不依賴內部實作細節 亦可撰寫程式。  這樣的好處之一 , 即是若日後類別需變更內部的實作 方式 , 但只要它仍提供相同的操作方法 , 則使用者也 不必修改使用到該類別的程式。
  • 45. 為成員變數撰寫存取方法  因此為了隱藏成員變數 , 我們就需適時地為成員變數 加上存取限制。一般而言 , 可使用下列的原則: ▪ 除非必要 , 最好所有成員變數都加上 private 存取限 制。 ▪ 如果使用此類別的程式需要透過成員來完成某件事 , 就由類別提供方法來完成。
  • 46. 為成員變數撰寫存取方法 ▪ 如果需要修改或是取得成員的值 , 就提供專門存取成 員的方法。 通常用來取得成員值的方法會命名為 getXXX, 其中 XXX 就是成員變數的名稱;相對的 , 用來設定成員值 的方法就稱為 setXXX 。 這樣一來 , 可以將更改成員的動作侷限在此方法中 , 往後對於除錯或是要為更改成員而引發的影響加上處 理工作時就會比較方便。
  • 47. 為成員變數撰寫存取方法  相同的道理 , 對於類別中所定義的方法 , 加上存取限 制的通則如下: ▪ 如果是要提供給外界呼叫的方法 , 請明確的標示為 public 存取限制。像是剛剛所提到的 get 、 set 方法 , 就是最好的例子。 ▪ 如果只是供類別中其他的方法呼叫的方法 , 請明確的 標示為 private 存取限制 , 以避免被類別外部的程式 呼叫。 ▪ 對於建構方法 , 除非有特別的用途 , 否則應該都標示 為 public, 因為若是標示為 private, 則 new 運算子 就無法呼叫建構方法 , 因而不能設定物件的初始狀態
  • 50. 為成員變數撰寫存取方法  在程式中第 10 〜 13 行 , 就為 Test 類別的 private 成員 x 、 y 提供了一組存取的方法 , 並分別 取名為 getX 、 setX 與 getY 、 setY, 同時也特別 將這 2 組存取方法都標示為 public 存取限制。  回頭看前一章的汽車類別範例 , 只要加上合適的建構 方法 , 並將成員變數設為 private, 就可讓它將資訊 隱藏起來 , 我們只能透過它所公開的方法來控制物件 。
  • 54. 為成員變數撰寫存取方法  以這種方式撰寫程式時 , main() 方法的內容看起來會 比較簡潔 , 因為其中大多是直接呼叫類別所提供的方 法 , 我們也比較能看出 main() 方法是在做什麼事。
  • 55. 9-2-3 傳回成員物件的資訊  透過前面幾個例子 , 相信大家都已對資訊隱藏有初步 的認識 , 原則就是將成員變數設為 private, 並提供 必要的公開方法。  但如果類別的成員變數是另一個類別的物件 , 則在設 計與此成員物件相關的公開方法時 , 要注意是否要將 這個私有成員物件 , 也公開到外部。  舉例來說 , 在平面幾何中 , 一個圓的可以由一個圓心 座標和半徑來定義。  因此我們可以先設計一個代表座標點的類別 Point, 然後再於圓的類別中用 Point 的物件代表圓心座標 , 例如。
  • 57. 傳回成員物件的資訊  在 Circle 類別中的 getP() 方法 , 其用途是讓外界 取得圓心座標 , 但如果直接傳回私有成員變數 p 的 參照 , 那麼外界就可取得此物件的參照 , 並透過此參 照呼叫 Point 類別的 setX() 、 setY() 方法。  如此一來就變成外界可直接修改私有成員物件了 , 請 參考以下的例子。
  • 61. 傳回成員物件的資訊  在第 20 行為 Circle 類別定義了一個取得圓心座標 的 getP() 方法 , 此方法直接將成員變數 p 傳回 , 也就是傳回圓心物件的參照。  因此當 main() 方法在第 36 行用 getP() 方法取得 圓心後 , 可在第 37 行用它呼叫 Point 類別的 setX() 方法來變更 X 軸座標。  由執行結果也可看到圓心的 X 軸座標的確被更改了 。
  • 62. 傳回成員物件的資訊  雖然這樣改變圓心座標的方式看似合理 , 但對 Circle 類別而言 , 卻失去『資訊隱藏』的特性 , 因為外界不 需透過它 , 即可任意變更其圓心座標。  雖然成員變數 p 確實是 private, 但因為 getP() 方 法是將其參照傳回 , 所以外界即可透過此參照直接存 取到私有的物件。  如果要保護 Circle 類別的內容 , 則可修改 getP() 方法 , 讓它變成傳回另一個座標值相同的 Point 物 件 , 而非傳回私有的 Point 物件參照。
  • 63. 傳回成員物件的資訊  如此一來外界仍能取得一個代表圓心座標的 Point 物件 , 但該物件並非 Circle 類別的成員 , 因而可達 到『資訊隱藏』的目的。修改後的程式如下:
  • 65. 傳回成員物件的資訊  這個範例與前一個範例有 2 個主要不同之處: 1. 第 15 〜 18 行為 Point 類別定義了另一個建建構 方法 , 此建構方法是用現有的點物件為參數 , 並複製 參數物件的座標值給新物件。 2. 第 25 〜 27 行的 getP() 方法 , 改成傳回一個新建 立的 Point 物件 , 而非私有的成員變數 p, 但建立 新物件時則是以 p 為參數 , 所以傳回的物件之座標 會與圓心相同。
  • 66. 傳回成員物件的資訊  經過上述的修改後 , 在 main() 中取得並修改圓心的 座標時 , 即不會動到 Circle 物件實際的圓心。  由執行結果可發現 , 程式最後顯示圓的資訊時 , 其圓 心座標並未被修改。  這兩個範例程式中 , 都為類別定義了一個 toString() 方法 , 這個方法會將物件的資訊以字串的形式傳回 , 這種設計方式 , 讓我們需要輸出物件資訊時 , 可以有 較彈性的用法 , 因為我們可利用 "+" 運算子將多個 字串組合在一起。 ▪ 在下一章即會進一步介紹 String 字串類別的用法。
  • 67. 9-2-4 JavaBean 的命名標準  JavaBean 是一種由 Java 語言所製作成的元件 (Component), 可以安裝到 Java 的整合發環境中 ( 例如 NetBeans 或 Eclipse), 讓設計師很輕鬆地將 之當成元件來使用其功能。  雖然本書不會介紹此進階功能 , 但建議讀者都能遵循 JavaBean 的命名標準 , 讓您的程式更具有可讀性及 通用性。 ▪ 如何以 JavaBean 的命名標準來為方法命名 , 也是 SCJP 的考試範圍喔 ( 但 JavaBean 的設計與使用則 不會考 ) !
  • 68. JavaBean 的命名標準  JavaBean 將成員變數稱為欄位 (field), 這些欄位必 須宣告為 private, 以符合封裝的要求。  類別中屬性與方法的命名標準和前面章節所介紹的相 同 , 就是開頭要小寫且後面的每個單字開頭要大寫 , 例如 name 、 isOpened 、 readFileData 。  此外 , 在撰寫存取欄位的 Getter ( 取值方法 ) 及 Setter ( 設值方法 ) 時 , 必須遵循一套特殊的規則。
  • 69. JavaBean 的命名標準  另外 , 還有一種支援事件處理的 Listener ( 監聽方 法 ) 也有特殊規則 , 底下就分別介紹這 3 種方法的 命名標準: ▪ Getter :用來讀取某個欄位 ( 成員變數 ) 的值 , 其宣 告的格式為: 其中存取控制必須為 public, 而 type 為要讀取欄位 的型別。 Xxx 要首字大寫 , 但不一定要和欄位名稱相同 , 只要 具備可讀性即可 , 例如 public int getSize() 、 public float getValue() 。
  • 70. JavaBean 的命名標準 此外 , 如果欄位的型別為 boolean, 那麼也可將 get 改為 is : 例如 isReady() 和 getReady() 都是正確的命名方式 。
  • 71. JavaBean 的命名標準 ▪ Setter :用來設定某個欄位 ( 成員變數 ) 的值 , 其宣 告的格式為: Setter 和 Getter 類似 , 但傳回值必須為 void, 而且 要接受一個參數 , 其型別和要設定欄位的型別相同。 例如 public void setSize(int x) 、 public void setValue(float f) 。
  • 72. JavaBean 的命名標準 ▪ Listener :用來加入 (add) 或移除 (remove) 某個事 件的監聽方法 , 格式如下: ▪ 開頭必須為 public void, 方法的名稱則必須為 add 或 remove, 後面接著事件監聽的類別名稱 XxxListener, 並接收一個事件監聽類別的參數。例如:
  • 73. 9-3 static 共享成員變數  前面的類別範例所建立的物件 , 都能擁有個自己的成 員變數 , 以表現物件屬性間的差異。  但在某些情況下 , 我們可能會想讓所有物件的某個屬 性都是相同的 , 此時就可使用 static 共享成員變數 來表現這個物件的共通屬性。
  • 74. static 共享成員變數  以我們示範過的汽車類別為例 , 假如該類別代表的是 某一款特定的車型 , 所有物件代表同型車的多個個體。 載油量當然會隨車子所加的油量、行駛的里程而隨時 變動;但耗油率我們可能想將之設為固定值 , 即所有 物件的耗油率都相同。  此時若單只是在建構物件時 , 將耗油率設為相同的數 值 , 並不方便 , 也不安全 , 因為如果寫程式時不小心 寫錯了 , 就會造成耗油率不一致等問題。  因此 Java 就提供 static 的成員變數 , 來解決這個 問題。
  • 75. 9-3-1 static 存取控制  當我們將類別的成員變數加上 static 存取控制字符 , 就表示所有屬於此類別的物件 , 都會共享這個成員 , 而非每一個物件擁有自己的一份成員。舉例來說:
  • 77. static 存取控制  在程式 18 〜 20 行雖然分別為物件的成員變數 y 設定不同的值 , 但由於該成員變數為 static , 所以其 實這 3 個物件的成員變數 y 是同一份 , 每次設定值 時 , 都是設定同一個 y, 因此最後一次呼叫建構方法 時將之設為 60 之後 , 不論是透過 a 、 b 、 c 參照 來取得成員變數 y 的值 , 都是 60 了。  反之 , 成員變數 x 則因為不是 static, 所以個別物件 都享有自己的一份。
  • 78. 9-3-2 使用類別名稱存取 static 成員變數  static 成員變數除了可用如同一般成員變數的方式存 取外 , 也可以透過類別名稱存取之。  以剛剛的 Test 類別 , 我們可以用如下的方式存取成 員變數 y :
  • 79. static 存取控制  在第 21 行以『類別名稱 . 成員變數名稱』的方式即 存取到 y, 並將它設為 100, 所以之後顯示物件內容 時 , 其 y 值都是 100 。
  • 80. static 存取控制  此外 , 我們甚至可在未建立物件的情況下 , 也能使用 類別的 static 成員變數:
  • 82. static 存取控制  在這個範例中 , Test 類別的建構方法只會設定成員變 數 x 的值。  而第 17 行則在未產生任何物件之前即存取 static 成員變數 y, 並設妥其值 , 所以之後的建構方法雖未 設定 y 的值 , 但由執行結果可看到各物件的 y 值都 是 100 。
  • 83. 9-3-3 static 初始區塊  由於 static 成員變數的共享特性 , 通常不會在建構 方法中設定其初值 , 因此 static 成員變數要不就是 在宣告的同時直接設定初值 , 要不就是另外單獨設定 。  為了避免寫程式時忘了設定 static 成員變數 , Java 還提供了 static 初始區塊 (Static Initializer), 可以 確保在產生物件之前 , 設定 static 成員。  其用法就是在類別的定義中 , 加入一個以 static 保 留字為首的大括號區塊 , 並在此區塊中加入初始化 static 成員變數的敘述 , 例如。
  • 86. static 初始區塊  在類別中的 static 區塊 , 會在程式使用到該類別之 前執行。  以上列程式為例 , 第 5 〜 7 行就是 static 初始區 塊 , 它會在程式中第一次使用到 Test 類別 ( 即第 23 行 ) 之前執行 , 因此第 23 行顯示的結果就是執 行過 static 初始區塊後的成員 y 的值 100 。
  • 87. static 初始區塊  由於 static 成員變數是由同一類別的所有物件所共 享 , 且不需先產生物件 , 即可以透過類別名稱存取 , 因此又稱為類別變數 (Class Variable) 。  相對的 , 非 static 的成員變數因為是每個物件各自 擁有一份 , 需建立物件後才能使用 , 因此稱為實體變 數 (Instance Variable) 。 ▪ 建立物件又可稱為建立一個實體 (Instance) 。
  • 88. 9-3-4 static 方法  static 除了可以使用在成員變數上以外 , 也可以應用 在方法上。  一個標示有 static 存取控制的方法除了可以透過所 屬類別的物件呼叫以外 , 也和 static 成員變數一樣 , 可以在沒有產生任何物件的情況下透過類別名稱呼叫 , 例如。
  • 90. static 方法  由於 static 成員變數及方法不需產生物件即可使用 的特性 , 因此可以用來提供一組相關聯的工具方法或 是常數值。  像是 Java 類別庫中的 Math 類別 , 就提供許多與 數學相關的 static 運算方法 ( 像是算次方、取亂數 、三角函數等等 ) 以及 static 常數值 ( 例如圓周 率)。
  • 91. static 方法  請特別注意 , 在 static 區塊或方法之中 , 不能用到 任何非 static 的成員變數以及方法 , 也不能使用 this 保留字。  這其實很容易理解 , 因為非 static 的成員變數和方 法是跟隨物件而生 , 而 static 區塊或方法可以在沒 有產生任何物件之前使用 , 此時因為沒有產生物件 , 自然就不會配置有非 static 的成員變數 , 而 this 也 沒有物件可指。
  • 92. 解開 main() 方法之謎  從這裡的解說就可以將 main() 方法的神秘面紗揭開 了 , 原來 main() 方法只是一個 public static 的方法 , 而且不會傳回任何值。
  • 93. 9-3-5 final 存取控制  static 成員變數常常用來提供給同一類別的所有物件 一份一致的資料 , 供所有的物件共用。  為達成此目的 , 還需要有一種方法 , 可以在設定好 static 成員變數的初值後就不能更改 , 否則各別物件 都隨意去更動 static 成員變數的值 , 就不是一份一 致的資料了。  為達到此目的 , 可以搭配第 3 章介紹過的 final 字 符 , 限制特定的 static 成員變數在設定過初值之後 就不允許更動 , 例如。
  • 95. final 存取控制  第 2 行中宣告了 x 是 final, 所以第 9 行的設定動 作在編譯時就會被視為錯誤。  要特別注意的是 , 一旦宣告了成員變數為 final 後 , 如果是 static 成員變數 , 那麼就必須要在宣告同時 或是在 static 初始區塊中設定初值。  如果是非 static 成員變數 , 就必須在宣告同時或是 在建構方法中設定初值 , 否則都會被視為是錯誤。
  • 96. 9-3-6 靜態變數與實體變數的預設值  凡是宣告在方法之外的變數 ( 靜態變數或實體變數 ), 除非宣告為 final 變數 ( 例如前一個範例 , 就必須設 定初值 ), 否則都會有預設值 , 如下表所示:
  • 98. 靜態變數與實體變數的預設值  以上程式的最後一行 , 就是因為 Test.z 的值為 null, 因此後面不可再用句點來存取其內的成員了。  此時我們也可加一個 i f 判斷式來避免此問題:
  • 99. 靜態變數與實體變數的預設值  從另一方面來看 , 凡是宣告在方法之內的變數 ( 稱為 區域變數 ) , 則不會有預設值 , 我們必須先設定變數 的值 , 然後才能讀取其內容 , 否則編譯器會視為錯誤 , 例如。
  • 100. 靜態變數與實體變數的預設值  在以上程式中 , 請注意陣列變數 (b) 在用 new 初始 化 ( 配置實體元素 ) 之後 , 其內的元素也會自動指定 初值 ( 因為陣列也是一種物件 ), 這在第 7 章已介紹 過了。 ▪ 凡是以 new 配置記憶空間的物件或陣列 , 其內的成 員變數或陣列元素都會具有預設值。
  • 101.  9-A 提供輔助工具的類別  9-B 善用多重定義
  • 103. What is the result? A. 5 4 3 2 B. 5 4 4 3 C. 5 5 4 3 D. 5 5 4 4 E. Compilation fails.
  • 104. 2. Which statements concerning following code are true? (Choose two or three)
  • 105. A. This class is fully encapsulated. B. B. The variables break the encapsulation of class. C. C. The methods break the encapsulation of class D. D. All methods are following the JavaBean standard. E. E. Some methods are not following the JavaBean standard.
  • 106. 3. Which of following methods are valid constructor for class Note? (Choose all that apply) A. public Note() { ... } B. public void Note() { ... } C. private Note() { ... } D. public static Note() { ... } E. Note() { ... } F. final Note() { ... }
  • 107. 4. Given following Java code:
  • 108. What is the result? A. C6 C1 C2 C3 C4 C5 B. C6 C1 C3 C4 C2 C5 C. C6 C1 C3 C4 C5 C2 D. C6 C4 C3 C1 C2 C5 E. C6 C4 C3 C1 C5 C2
  • 109. 5. A JavaBean Class has following field: Which method declaration follows JavaBean standard? (Choose all that apply) A. public void getVisible() B. public boolean getVisible() C. private boolean isVisible() D. public boolean isVisible() E. public boolean canVisible() F. private boolean canVisible()
  • 110. 6. Given: Which four statements are true? (Choose four) A. fun1() can directly modify field i. B. fun1() can directly modify field j. C. fun2() can directly modify field i. D. fun1() can directly call fun2(). E. fun2() can directly call fun1(). F. StaticQuiz.fun1() is a valid invocation outside StaticQuiz class. G. StaticQuiz.fun2() is a valid invocation outside StaticQuiz class.
  • 111.
  • 113. How many objects are created in main()? How many object is available for Garbage Collection at line 13? A. 2 objects are created. B. 4 objects are created. C. 5 objects are created. D. 1 object is avaible for Garbage Collection. E. 2 object is avaible for Garbage Collection. F. 3 object is avaible for Garbage Collection.
  • 114. 8. What is the result of following program:
  • 115. A. B. C. D. E. Counter=2 Compilation fails at line 3. Compilation fails at line 4. Compilation fails at line 9. Compilation fails at line 10. F. Runtime error.
  • 116. 9. Given: What is the result? A. 300 200 B. 200 300 D. 250 300 E. 250 250 C. 300 250
  • 117.
  • 118. 10.Given: How many objects are available for Garbage Collection at line 14? A. 0 B. 1 C. 2 D. 3 E. 4