《Java編程思想》第一章:對象導論

    本人的筆記風格是,將書中的重要知識點摘抄出來,若是是特別轉彎的話,本人會用本身的理解進行說明。從如今開始講讀書筆記一篇一篇的拋出來,供你們參閱學習討論,若是錯誤的地方,請批評指正。首先是《Java編程思想》。java

第一章:對象導論

    「咱們之因此將天然界分解,組成各類概念,並按其含義分類,主要是由於咱們是整個口語交流社會共同遵照的協定的參與者,這個協定以語言的形式固定下來……除非同意這個協定中規定的有關語言信息的組織和分類,不然咱們根本沒法交談」程序員

——Benjamin Lee Whorf(1897~1941)數據庫

    (本人很是喜歡這段話,就摘了出來,完美的詮釋了語言對於人類的意義於做用。)編程

    計算機革命起源於機器,所以,編程語言的產生也始於對機器的模仿。小程序

    本章將介紹包括開發方法概述在內的OOP(Object-oriented Programming)的基本概念。數組

一、抽象過程

    全部編程語言都提供抽象機制。(我的認爲,抽象很重要,這是一我的進入編程行當的基礎,若是沒有想象和聯想的能力,建議你仍是不要從事編程行業了,否則會很吃力,或許轉個行業對你來講會很好!)瀏覽器

    程序員必須創建起在機器模型和實際待解決問題的模型之間的關聯。創建這種映射是費力的,並且這不屬於編程語言所固有的功能,這使得程序難以編寫,而且維護代價高昂,同時也產生了做爲副產物的整個「編程方法」行業。(這一句話就說明了抽象的重要性。)安全

    另外一種對機器建模的方式就是隻針對待解決問題建模。(簡化工做的開始)服務器

    面向對象方式經過向程序員提供表示問題空間中的元素的工具而更近了一步。咱們將問題空間中的元素及其在解空間中的表示稱爲「對象」。(若是沒有想象和聯想,這一句話很難理解。)網絡

    Alan Kay曾總結了第一個成功的面嚮對象語言——Smalltalk的五個基本特性:

    1.萬物皆爲對象。

    2.程序是對象的集合,它們經過發送消息來告知彼此索要作的。

    3.每一個對象都有本身的由其餘對象所構成的存儲。

    4.每一個對象都擁有其類型。

    5.某一特定類型的全部對象均可以接收一樣的消息。

    此語言也是Java所基於的語言之一。

    Booch對對象提出了一個更加簡潔的描述:對象具備狀態、行爲和標識。

    對象的狀態:內部提供的數據。

    對象的行爲:對象內部的方法。

    對象的標識:對象在內存中有一個惟一的內存地址。用於區分不一樣的對象。

    (我的理解,其實對象就是一個事物在程序中的一個縮影,引用就至關於給對象起個名字。名字能夠隨時更改,可是對象自己性質不會改變。能夠先將一個對象侷限性的理解爲一我的,完全理解以後,再擴大的想象,將它類比爲全部你能類比的東西。)

二、每一個對象都是一個接口

    全部的對象都是惟一的,但同時也是具備相同的特性和行爲的對象所歸屬的類的一部分。程序中使用基本關鍵字class來引入新的類型。事實上,全部的面向對象程序設計語言都是用class這個關鍵字來表示數據類型。

    建立抽象數據類型(類)是面向對象程序設計的基本概念之一。

    類描述了具備相同特性和行爲的對象集合,一個類實際上就是一個數據類型。

    面向對象方法並非僅侷限於構建仿真程序。面向對象技術的應用確實能夠將大量的問題很容易的降解爲一個簡單的解決方案。

    事實上,面向對象程序設計的挑戰之一,就是在問題空間的元素和解空間的對象之間建立一對一的映射。

    每一個對象都只能知足某些請求,這些請求由對象的接口(interface)所定義,決定接口的即是類型。

    接口肯定了對某一特定對象所能發出的請求。可是,在程序中必須有知足這些請求的代碼。這些代碼與隱藏的數據一塊兒構成了實現。

    建立一個對象的方式:

    定義這個對象的「引用」(It),而後調用new方法來建立該類型的新對象。爲了向對象發送消息,須要聲明對象的名稱,並以圓點符號連接一個消息請求。

    例如:

String str = new String();//建立對象
str.toString();//發送消息請求

    下圖是UML(Unified Modelling Language,統一建模語言)形式的圖,每一個類都用一個方框表示,類名在方框的頂部,你所關心的任何數據成員都描述在方框的中間部分,方法在方框的底部。一般只有類名和公共方法被展現於UML設計圖中。

三、每一個對象都提供服務

    當正在試圖開發或者理解一個程序設計時,最好的方法之一就是將對象想象爲「服務提供者」。程序自己將向用戶提供服務,它將經過調用其餘對象提供的服務來實現這一目的。你的目標就是去建立可以提供理想的服務來解決問題的一系列對象。

    將對象看做是服務提供者還有一個附帶的好處:它有助於提升對象的內聚性。高內聚是軟件設計的基本質量要求之一:這意味着一個軟件構件的各個方面「組合」的很好。

    將對象做爲服務提供者看待是一件維達的簡化工具,這不只僅在設計的過程當中很是有用,在其餘人理解和重用你的代碼時變得簡單。

四、被隱藏的具體實現

    程序開發人員按照角色分爲類建立者和客戶端程序員。(我的理解爲:架構師和普通開發人員)

    客戶端程序員的目標是收集各類用來實現快速應用開發的類。

    類建立者的目標是構建類,這種類只向客戶端程序員暴露必須的部分,而隱藏其餘部分。隱藏的部分一般表明對象內部脆弱的部分,它們很容易被粗心或者不知內情的客戶端程序員所毀壞,將此隱藏能夠減小bug。

    在任何相互關係中,具備關係所涉及的各方都遵照的邊界是十分重要的事情。訪問控制的第一個存在緣由就是讓客戶端程序員沒法觸及他們不該該觸及的部分。訪問控制的第二個存在緣由就是容許庫設計者能夠改變類內部的工做方式而不用擔憂會影響到客戶端程序員。

    Java用三個關鍵字在類的內部設定邊界:public、private、protected。

    public表示緊隨其後的元素對任何人都是可用的。(最大權限)

    private表示除了類型建立者和類型的內部方法以外的任何人都不能訪問的元素。(最小權限)

    protected表示繼承的類能夠訪問。

    Java還有一種默認的訪問權限,不使用任何關鍵字,這種權限一般被稱爲包訪問權限,只能同包的類能夠互相訪問其元素,包外的類訪問不了包內這種權限的類元素。

五、複用具體實現

    代碼複用是面向對象程序設計語言所提供的最了不得的優勢之一。

    使用現有的類合成新的類被稱爲組合(composition),若是組合是動態發生的,那麼它一般被稱爲聚合(aggregation)。組合一般被視爲「has-a」的關係。

    組合帶來了極大的靈活性,在創建新類時,應該首先考慮組合。

六、繼承

    對象這種概念,自己就是十分方便的工具,使得你能夠經過概念將數據和功能封裝到一塊兒,所以能夠對問題空間的觀念給出恰當的表示,而不用受制於必須使用底層機器語言,這些概念用關鍵字class來表示,它們造成了編程語言中的基本單位。

    經過繼承能夠達到複製起因類並加以改造(添加和修改)建立出新類。原有類被稱做基類、超類或者父類,新建立的類被稱做導出類、繼承類或者子類。

    類型不只僅只是描述了做用於一個對象集合上的約束條件,同事還有與其餘類型之間的關係。

    繼承使用基類型和導出類型的概念表示了這種類型之間的類似性。一個基類型包含其導出類型所共享的特性和行爲。能夠建立一個基類型來表示系統中某些對象的核心概念,從基類型中導出其餘類型,來表示此核心能夠被實現的各類不一樣方式。

    例以下圖:

    當繼承現有類型時,也就是建立了新的類型。這個新的類型不只包括現有類型的全部成員(儘管private成員被隱藏了起來,而且不可訪問),並且更重要的是它複製了基類的接口。也就是說,全部能夠發送給基類對象的消息同時也能夠發送給導出類對象。這就意味着處處類與基類具備相同的類型。

    因爲基類和導出類具備相同的基礎接口,因此伴隨此接口的一定有某些具體實現。當對象接收到特定的消息時,必須有某些代碼去執行。若是隻是簡單的繼承,而不作任何改變的話,這就意味着導出類與基類擁有相同的類型和相同的行爲,這樣作是沒有意義的。

    有兩種方法可使基類和導出類產生差別:

    一是直接在導出類中添加新方法。二是改變現有基類的方法的行爲,這被稱做覆蓋(overriding)。

1.is-a和is-like-a

    若是繼承只覆蓋基類的方法,就意味着導出類和基類是徹底相同的類型,就能夠用一個導出來對象來徹底替代一個基類對象,這能夠被視爲純粹替代,一般稱做替代原則。咱們常常將這種狀況下的基類與導出類之間的關係成爲is-a關係。

    判斷是否繼承,就是要肯定是否能夠用is-a來描述類之間的關係,並使之具備實際意義。

    若是在導出類型中添加新的接口元素,這樣也就擴展了接口。這個新的類型仍然能夠替代基類,可是這種替代並不完美,由於基類沒法訪問新添加的方法。這種狀況咱們能夠描述爲is-like-a關係。新類型具備舊類型的接口,可是它還包含其餘方法,因此不能說它們徹底相同。

​​​​​​​七、伴隨多態的可互換對象

    在處理類型的層次結構時,常常想把一個對象不看成它所屬的特定類型來對待,而是將其看成其基類的對象來對待。這使得人們能夠編寫出不依賴於特定類型的代碼。

    這樣的代碼時不會受添加新類型影響的,並且添加新類型是擴展一個面向對象程序以便處理新狀況的最經常使用方式。經過導出新的子類型而輕鬆擴展設計的能力是對改動進行封裝的基本方式之一。這種能力能夠極大的改善咱們的設計,同時也下降然間維護的代價。

    在試圖將導出類型的對象看成其泛化(generic)基類型對象來看待時,仍然存在一個問題:代碼執行的時候到底該調用誰?

    一個非面向對象編程的編譯器產生的函數調用會引發所謂的前期綁定。前期綁定就是編譯器將產生對一個具體函數名字的調用,而運行時將這個調用解析到將要被執行的代碼的絕對地址。

    爲了解決上述問題,面向對象程序設計語言使用了後期綁定的概念。後期綁定就是當向對象發送消息時,被調用的代碼知道運行時才能肯定。

    編譯器確保被調用方法的存在,並對調用參數和返回值執行類型檢查,可是並不知道將被執行的確切代碼。沒法提供此類保證的語言被稱爲弱類型語言。

    爲了執行後期綁定,Java使用一小段特殊的代碼來代替聚堆地址調用。這段代碼使用在對象中存儲的信息來計算方法體的地址。

    Java中動態綁定是默認行爲,不須要添加額外的關鍵字來實現多態。

    把導出類看作是其基類的過程稱爲向上轉型(upcasting)。

    一個面向對象程序確定會在某處包含向上轉型,由於這是將本身從必須知道確切類型中解放出來的關鍵。

​​​​​​​八、單根繼承結構

    在Java中,全部的類最終都繼承自單一的基類,這個終極基類的名稱就是Object。

    單根繼承的好處:

    在單根繼承結構中的全部對象都具備一個共用接口,因此它們歸根結底都是相同的基本類型。

    單根繼承結構保證全部對象都具有某些功能。Java中Object類的方法就能夠看作是對象都具有的功能。

    單根繼承結構使垃圾回收器的實現變得容易得多。

​​​​​​​九、容器

    建立另外一種對象類型,這種新的對象類型持有對其餘對象的引用,這一般被稱做容器,固然也包括數組。

    好的OOP語言都有一組容器,它們做爲開發包的一部分。Java在其標準類庫中也包含有大量的容器。在某些類庫中,一兩個通用容器足夠知足全部的需求,可是在其餘類庫中,具備知足不一樣需求的各類類型的容器。例如:List、Map、Set以及諸如隊列、樹、堆等更多的構件。

    須要針對容器進行選擇有兩個緣由:

  • 不一樣容器提供了不一樣類型的接口和外部行爲。
  • 不一樣的容器對於某些操做具備不一樣的效率。

1.參數化類型

    Java SE5的重大變化之一就是在增長了參數化類型,在Java中稱爲泛型。一對尖括號,中間包含類型信息,經過這些特徵就能夠識別對泛型的使用,例如:

ArrayList<String> strList=new ArrayList<String>();

    泛型規定了容器中存儲的數據類型,這樣就避免了轉型帶來的麻煩。

​​​​​​​十、對象的建立和生命期

    Java中徹底採用動態內存分配方式。每當須要建立新對象時,使用new關鍵字累構件對象的動態實例。

    動態方式是在被稱爲堆(heap)的內存池中動態的建立對象。動態方式能夠在須要對象的時候直接在堆中建立。由於存儲空間是是正賽運行時被動態管理的,因此須要大量的時間在堆中分配空間。

    動態方式有一個通常性的邏輯假設:對象趨向於變的複雜,因此查找和設防存儲空間的開銷不會對對象的建立形成重大沖擊。

    動態方式所帶來的更大的靈活性正是解決通常化編程問題的要點所在。

    Java提供了被稱爲「垃圾回收器」的機制,它能夠自動發現對象什麼時候再也不被使用,並繼而銷燬它。Java的垃圾回收器被設計用來處理內存釋放問題。

​​​​​​​十一、異常處理:處理錯誤

    自從編程語言問世以來,錯誤處理就詩中是最困難的問題之一。

    異常處理將錯誤處理直接置於編程語言中,有時甚至置於操做系統中。異常是一種對象,它從出錯地點被「拋出」,並專門設計用來處理特定類型錯誤的相應的一場處理器「捕獲」。異常不能被忽略,因此保證必定會在某處獲得處理。最後須要指出的是:異常提供了一種從錯誤情況進行可靠恢復的途徑。如今再也不是隻能退出程序,你能夠常常進行校訂,並恢復程序的執行,這些都有助於編寫出更健壯的程序。

    Java一開始就內置了異常處理,並且強制你必須去使用它。它是惟一可接受的錯誤報告方式。若是沒有編寫正確的處理異常的代碼,那麼就會獲得一條編譯時的出錯消息。這種有保障的一致性有時會使得錯誤處理很是容易。

    異常處理不是面向對象的特徵,異常處理在面嚮對象語言出現以前就已經存在了。

​​​​​​​十二、併發編程

    在計算機編程中有一個基本概念,就是在同一時刻處理多個任務的思想。

    併發:把問題切分紅多個可獨立運行的部分(任務)。

    在程序中這些彼此獨立運行的部分稱之爲線程。線程只是一種爲單一處理器分配執行時間的手段。若是操做系統支持多處理器,那麼每一個任務均可以被指派給不一樣的處理器,而且他們是在真正的並行執行。

    併發存在一個隱患:共享資源。所以,整個執行過程應該是:某個任務鎖定某項資源,完成其任務,而後釋放資源鎖,使其餘任務可使用這項資源。

    Java的併發是內置於語言中的,Java SE5已經增添了大量額外的庫支持。

​​​​​​​1三、Java與Internet

    Java對於解決傳統的單機程序設計問題很是有用,更重要的是,它解決了在萬維網(WWW)上的程序設計問題。

​​​​​​​1.Web是什麼

    要理解Web是什麼就必須先理解客戶/服務器系統。

​​​​​​​1>客戶/服務器計算技術

    客戶/服務器系統的核心思想是:系統具備一箇中央信息存儲池(central repository of information),用來存儲某種數據,它一般存在於數據庫中,大家能夠根據須要將它分發給某些人員或機器集羣。

    信息存儲池、用於分發信息的軟件以及信息與軟件所駐留的機器或集羣被總稱爲服務器。

    保證一個客戶插入的新數據不會覆蓋另外一個客戶插入的新數據,也不會在將其添加到數據可的過程當中丟失,這被稱爲事務處理。

    性能問題:可能在任意時刻都有成百上千的客戶向服務器發出請求,因此任何小的延遲都會產生重大影響。爲了將延遲最小化,程序員努力減輕處理任務的負載,一般是分散給客戶端機器處理,但有時也會使用所謂的中間件將負載分散給在服務器端的其餘機器。(中間件也被用來提升可維護性。)

​​​​​​​2>Web就是一臺巨型服務器

    Web實際上就是一個巨型客戶/服務器系統。

    Web瀏覽器包含了這樣的概念:一段信息不經修改就能夠在任意型號的計算機上顯示。

    瀏覽器只是一個觀察器,所以它甚至不能執行最簡單的計算任務。另外一方面,它倒是安全的,由於它在你的本地機器上不會執行任何程序,而這些程序有可能包含bug和病毒。

    爲了加強瀏覽器的功能,人們採用了各類不一樣的方法。首先,圖形標準獲得了加強,使得在瀏覽器中能夠播放質量更好的動畫和視頻。

    客戶端編程:引入在客戶端瀏覽器中運行程序的能力。

​​​​​​​2.客戶端編程

    Web最初的「服務器-瀏覽器」設計是爲了可以提供交互性的內容。但其實交互性徹底由服務器提供。服務器產生靜態頁面,提供給只能解釋並顯示它們的客戶端瀏覽器。

    基本的HTML(HyperText Markup Language,超文本標記語言)包含有簡單的數據收集機制:文本輸入框、複選框、單選框、列表和下拉式列表以及按鈕——它只能被編程來實現復位表單上的數據或提交表單上的數據給服務器。

    這種提交動做經過全部的Web服務器都提供的通用網關接口(common gateway interface,CGI)傳遞。提交內容會告訴CGI應該如何處理它。實際上你能夠經過CGI作任何事。然而構建於CGI程序之上的網站可能會迅速變得過於複雜而難以維護,並同時產生響應時間過長的問題。CGI程序的響應時間依賴於所必須發送的數據量的大小,以及服務器和Internet的負載,此外啓動CGI程序也至關慢。

    客戶端編程意味着Web瀏覽器能用來執行任何它能夠完成的工做,使得返回給用戶的結果更加迅捷,並且使得你的網站更加具備交互性。

    客戶端編程的問題:它與一般意義上的編程十分不一樣,參數幾乎相同,而平臺不一樣。

​​​​​​​1>插件

    客戶端編程所邁出的最重要的一步就是插件(plug-in)的開發。經過這種方式,程序員能夠下載一段代碼,並將其插入到瀏覽器中適當的位置,以此來爲瀏覽器添加新功能。

    插件對於客戶端編程的價值在於:它容許專家級的程序員不需通過瀏覽器生產廠商的許可,就能夠開發某種語言擴展,並將它們添加到服務器中。所以插件也至關於提供了一個「後門」。

​​​​​​​2>腳本語言

    插件引起了瀏覽器腳本語言(scripting language)的開發。經過使用某種腳本語言,你能夠將苦短程序的源代碼直接嵌入到HTML頁面中,解釋這種語言的插件在HTML頁面被顯示時自動激活。

    優勢:至關易於理解,能夠被快速加載。

    缺點:代碼會暴露給任何人去瀏覽。

    在Web瀏覽器內部使用的腳本語言實際上老是被用來解決特定類型的問題,主要是用來建立更豐富、更具備交互性的圖形化用戶界面(graphic user interface,GUI),腳本語言能夠解決客戶端編程中所遇到的百分之八十的問題,因此在考慮解決方案的時候應優先考慮腳本語言。

​​​​​​​3>Java

    Java不只是一種功能強大的、安全的、跨平臺的、國際化的編程語言,並且它還在不斷地被擴展,以提供更多的語言功能和類庫,可以優雅地處理在傳統編程語言中很難解決的問題,例如併發、數據庫訪問、網絡編程和分佈式計算。

    Java是經過applet以及使用Java Web Start來進行客戶端編程的。

    applet是隻在Web瀏覽器中運行的小程序,它是做爲網頁的一部分而自動下載的。當applet被激活時,它便開始執行一個程序,它提供一種分發軟件的方法,一旦用戶須要客戶端軟件時,就自動從服務器把客戶端軟件分發給用戶。用戶獲取最新版本的客戶端軟件時不會產生錯誤,並且也不須要很麻煩的從新安裝過程。

    只要一臺計算機有瀏覽器,且瀏覽器內置了Java解釋器,那麼這個程序就能夠自動在這臺計算機上運行。還能夠在數據提交以前作數據校驗,減小網絡帶寬的傳輸。

​​​​​​​4>備選方案

    實際上,applet並無大規模的應用,有如下幾個緣由:

    1.安裝Java運行時環境(JRE)必須10M帶寬。

    2.微軟沒有在IE(Internet Explorer)中包含JRE

    那麼就須要幾個備選方案:

    Macromedia的Flex,它容許你建立基於Flash的與applet至關的應用,Flash Player在超過98%的Web瀏覽器上均可用,因此編程時無需擔憂瀏覽器的相關性。

    ActionScript語言是基於ECMAScript的。

​​​​​​​5>.NET和C#

    曾經,Java applet的主要競爭對手是微軟的ActiveX。ActiveX要求客戶端必須運行在Windows平臺。

    .NET平臺大體至關於Java虛擬機(JVM)和Java類庫,而C#毫無疑問與Java有相似之處。

    .NET最受關注的問題就是微軟是否容許將它徹底地移植到其餘平臺。微軟宣稱這麼作沒有問題,並且Mono項目已經有一個在Linux上運行的.NET的部分實現,可是還不穩定。

​​​​​​​6>Internet與Intranet

    Web是最經常使用的解決客戶端/服務器問題的方案,能夠解決如下問題:

    1.客戶端計算機多種型號。

    2.安裝軟件的麻煩。

    3.軟件升級的麻煩,瀏覽器方式下的升級是透明的、自動的。

    當Web技術僅限於特定公司的信息網絡時,它被稱爲Intranet(企業內部網)。Intranet比Internet提供了更高的安全性,由於能夠屋裏地控制對公司內部服務器的訪問。在Intranet上,你能夠對本身的代碼質量負責,而且在發現bug以後能夠修復它們。

    當面對各類使人眼花繚亂的解決客戶端編程問題的方案時,最好的方法就是進行性價比分析。認真考慮問題的各類限制,而後思考那種解決方案能夠成爲最短的捷徑。

​​​​​​​3.服務器端編程

    Java取得巨大成功的因素之一就是服務器端編程。

    涉及到對數據庫的修改,這些數據可請求必須經過服務器端的某些代碼來處理,這就是所謂的服務器端編程。

    基於Java的Web服務器使用Java編寫被稱爲servlet的程序來實現服務器端編程。servlet及其衍生物JSP,是許多開發網站的公司遷移到Java上的兩個主要的緣由,尤爲是由於他們消除了處理具備不一樣能力的瀏覽器時所遇到的問題。

    服務器端編程的具體介紹請看《企業Java編程思想》。

​​​​​​​1四、總結

    編寫良好的Java程序一般比過程型程序要簡單得多,並且也易於理解得多。

    使用Java只須要關心如下兩部份內容的定義:用來表示問題空間概念的對象,以及發送給這些對象的用來表示在此空間內的行爲的消息。

    對於設計良好的程序,經過閱讀它就能夠很容易地理解其代碼。一般,其代碼也會少不少,由於許多問題均可以經過重用現有的類庫代碼而獲得解決。

    我的總結

    此章內容,將Java從頭至尾大體上介紹了一遍,若是是初學者,確定會很懵,只有對Java有必定了解的人,纔能有些理解,對初學者的建議是忽略此章,從第二章開始學習,最後,再來看此章節。

下一篇:《Java編程思想》第二章:一切都是對象

相關文章
相關標籤/搜索