java 程式設計思想的學習筆記 - 第一章

以技入道發表於2017-08-25

開篇: 本系列文章是用來記錄 java程式設計思想的 學習筆記,以及記錄自己的理解 ,主要目的是促進自己對java 的進一步瞭解

文章中如有描述或者理解有問題的部分 請博友告知,以便共同交流進步

第一章 物件引論

抽象過程

所有的變成語言都提供抽象機制。可以認為,你所能夠解決問題的複雜性直接取決於抽象的型別和質量。
上面所說的抽象型別 這裡舉例說明下

組合語言是對底層機器的抽象

底層機器   --> 組合語言  

接著出現的命令語言  FORTRAN、BASIC、C 等  是對組合語言的抽象,這些語言在組合語言之上有了大幅的改進,但是它們所作的主要抽象仍要求你在解決問題時要基於計算機的結構,而不是基於你試圖要解決的問題的結構來考量。

組合語言 --> FORTRAN、BASIC、C 等  

j ava等面嚮物件語言的抽象是 將物件-->抽象為java物件 

每個物件都擁有狀態、行為、和標識。這意味著每個物件都可以擁有內部資料和方法,並且每個物件都可以唯一的和其他物件區分開,具體來說就是每個物件在記憶體中都有唯一的地址。

當你正是如開發或理解一個程式設計時,最好的方法之一就是將物件想象為“服務提供者。你的程式本身將向使用者提供服務,它將通過呼叫其它物件提供的服務來實現這一目的。

將物件看作是服務提供者還有一個附加的好處:它有助於提高物件的內聚性(cohesiveness)。//ps:有點和設計模式接軌的意思

被隱藏的具體實現

將程式開發人員按照角色分為類建立者(可理解為後端) 和客戶端程式設計師(可理解前端或者介面呼叫方)是大有裨益的。

類建立者的目標是構建類,該類只向客戶端程式設計師暴露必需的部分,而隱藏其它所有部分。為什麼要這樣呢?因為如果加以隱藏,那麼客戶端程式設計師將不能夠訪問它,這意味著類建立者可以任意修改被隱藏的部分,而不用擔心對其他任何人造成影響。被隱藏的部分通常代表物件內部脆弱的部分,它們很容易被粗心的或不知內情的客戶端程式設計師所毀壞,因此將實現隱藏起來可以減少程式的Bug。

如果沒有任何訪問控制,所有東西都將赤裸裸暴露在外面.

訪問控制的第一個存在原因就是讓客戶端程式設計師無法觸及他們不應該觸及的部分

訪問控制的第二個存在原因就是允許庫設計者可以改變類內部的工作方式而不用擔心是否會影響到客戶端程式設計師。(是指呼叫方式吧)

java裡的這種訪問控制是通過三個關鍵詞來控制的: public 、private 、protected

public 表示緊隨其後的元素對任何人都是可用的。

private 這個關鍵字表示除型別建立者和該型別的內部方法之外的任何人都不能訪問的元素。private 就像你與客戶端程式設計師之間的一堵磚牆,如果有人試圖訪問 private 成員,就會在編譯時刻得到錯誤資訊。

protected和private差別僅在於繼承類(Inheriting class)可以訪問 protected成員,但是不能訪問 private 成員。(子類可以訪問protected)

Java 還有一種預設(default)的訪問許可權,包內可訪問。

複用具體實現

最簡單的複用某個類的方式就是直接使用該類的一個物件,此外你也可以將該類的一個物件置於某個新的類中。我們稱其為“建立一個成員物件”。 --聚合關係   組合關係是擁有關係,比如 car 類引用輪胎,引擎,座位等物件 。而聚合只是是引用。

實際上,在建立新類時,你應該首先考慮組合,因為它更加簡單而靈活。如果你採用這種方式,你的設計會變得更加清晰。一旦有了一些經驗之後,你便能夠看透必須使用繼承的場合。

繼承:複用介面

介面是用來解決在建立了一個類之後,即使另一個新類與其具有相似的功能,你還是得重新建立一個新類。如果我們能夠以現有的類為基礎,複製它,然後通過新增和修改這個副本來建立新類那就要好得多了。

一個基類包含其所有匯出類共享的特性和行為。你可以建立一個基類來表示系統中某些物件的核心概念,從基類中匯出其它的類,來表示此核心可以被實現的各種不同方式。


例子是經典的在計算機輔助設計系統或遊戲模擬系統中可能被泳道的幾何形(shape)的例子。基類是 shape,每一個 shape 都具有尺寸、顏色、位置等,同時每一個 shape 都可以被繪製、擦除、移動和著色等。在此基礎上,可以匯出(繼承出)具體的幾何形狀——圓形、正方形、三角形等——每一種都具有額外的特性和行為,例如某些形狀可以被翻轉。某些行為可能並不相同,例如面積計算。型別層次結構同時體現了幾何形狀之間的相似性和相異性。





在 Java中,動態繫結是預設行為,你不需要新增額外的關鍵字來實現多型(polymorphism)。


抽象基類和介面

Interface(介面)這個關鍵字比抽象類的概念更進了一步,它壓根不允許有任何方法定義。介面是一個非常方便而通用的工具,因為它提供了介面與實現的完美分離。此外,只要你願意,你就可以將多個介面組合到一起,與之相對照的,你要繼承多個一般類或抽象類卻是不可能的。



物件的建立、使用和生命週期

物件最重要的要素之一便是它們的生成和銷燬。

C的效率是重要議題,所以為了追求效率把控制選擇權交給了程式設計師,但是失去了靈活性,過於受限。

Java 提供了被稱為“垃圾回收器(garbage collector)”的機制,它可以自動發現物件何時不再被使用,並繼而銷燬它。垃圾回收器非常有用,因為它減少了你必須考慮的議題和你必須編寫的程式碼。更重要的是,垃圾回收器提供了更高層的保障,可以避免暗藏的記憶體洩漏問題

集合(collection)與迭代器(iterator

有兩個原因使得你還是需要對容器有所選擇。第一,不同容器提供了不同型別的介面和外部行。堆疊與佇列就具備不同的介面和行為,也不同於集合(set)和列表。其中某種容器提供的問題解決方案可能比其它容器要靈活的多。第二,不同的容器對於某些操作具有不同的效率。

最好的例子就是兩種 List 的比較:ArrayList 和 LinkedList。它們都是具有相同介面和外部行為的簡單的序列,但是它們對某些操作所花費的代價卻有天壤之別。在 ArrayList 中隨機訪問元素是一個花費固定時間的操作,但是,對 LinkedList 來說,隨即選取元素需要在列表中移動,其代價是高昂的,訪問越靠近表尾的元素,花費的時間越長。

另一方面,如果你想在序列中間插入一個元素,LinkedList 的開銷卻比 ArrayList 要小。 

單根繼承結構

在單根繼承結構中的所有物件都具有一個共用介面,所以它們歸根到底都是相同的基本型別。Object

向下轉型(downcasting)與模板/泛型(template/generic

向下轉型(Object-->int)和執行時刻的檢查需要額外的程式執行時間和程式設計師心血。那麼建立知道自己所儲存物件的型別的容器,從而消除向下轉型的需求和犯錯誤的可能不是更有意義嗎?其解決方案被稱為引數化型別(parameterized type)機制。引數化型別就是編譯器可以自動定製作用於特定型別之上的類。例如,通過使用引數化型別,編譯器可以定製一個只接納和取出 Shape物件的容器。 另可通過泛型定義

確保正確清除

例如,假設你正在為某個機場設計空中交通管理系統。一開始問題似乎很簡單:建立一個容器來儲存所有的飛機,然後為每一架進入控制交通控制區域的飛機建立一個新的飛機物件,並將其置於容器中。對於清除工作,只需在飛機離開此區域時刪除相關的飛機物件即可。

但是,可能還另有某個系統記錄著有關飛機的資料,也許這些資料不需要像主要的控制功能那樣立刻受到人們的注意。例如,它可能記錄著所有飛離飛機場的小型飛機的飛行計劃。因此你需要有第二個容器用來存放小型飛機,無論何時,只要建立的是小型飛機物件,那麼它同時也應該置入第二個容器內。然後某個後臺程式在空閒時間對第二個容器內的物件執行操作。

Java 的垃圾回收器被設計用來處理記憶體釋放問題(儘管它不包括清除物件的其他方面)。垃圾回收器“知道”物件何時不再被使用,並自動釋放該物件的記憶體。這與所有物件都是繼承自單根基類 Object,以及你只能以一種方式建立物件——在堆上建立這兩個特性一起,使得用 Java 程式設計的過程較之用 C++程式設計要簡單得多,你要做的決策和要克服的障礙都要少得多。

垃圾回收與效率和靈活性

java垃圾回收機制在提供程式設計方便的同時是消耗了記憶體和執行效率座位代價的.

異常處理:處理錯誤

Java 的異常處理在眾多的程式語言中格外引人注目,因為 Java 一開始就內建了異常處理,而且強制你必須使用它。如果你沒有編寫正確的處理異常的程式碼,那麼你就會得到一條編譯時刻的出錯訊息。這種得到確保的一致性有時會使得錯誤處理非常容易。

併發(concurrency

通常,執行緒只是一種為單一處理器分配執行時間的手段。但是如果作業系統支援多處理器,那麼每個執行緒都可以被指派給不同的處理器,並且它們是在真正地並行執行。在語言級別上多執行緒所帶來的便利之一便是程式設計師不用再操心機器上有多個處理器還是隻有一個處理器。由於程式被邏輯化分為執行緒,所以如果機器擁有多個處理器,那麼程式將在不需要特殊調整的情況下執行得更快。

所有這些都使得執行緒看起來相當簡單,但是有一個隱患:共享資源。如果有超過一個的並行執行緒都要訪問同一項資源,那麼就會出問題。例如,兩個程式不能同時向一臺印表機傳送資訊。為了解決這個問題,可以共享的資源,例如印表機,必須在被使用期間鎖定。因此,整個過程是;某個執行緒鎖定某項資源,完成其任務,然後釋放資源鎖,使其它執行緒可以使用這項資源。

Java 的執行緒機制是內建於其中的,它使此複雜課題變得簡單得多了。執行緒機制被物件層次所支援,因此執行緒的執行可以用物件來表示。Java 同時也提供了限制性資源鎖定功能,它可以鎖定任何物件所佔用的記憶體(畢竟這也算是某種共享資源),使得同一時刻只能有一個執行緒在使用它。這是通過 synchronized 關鍵字來實現的。其它型別的資源必須由程式設計師顯式地鎖定,通常是通過建立一個表示鎖的物件,所有執行緒在訪問資源之前先檢查這個物件。(沒懂這塊)




相關文章