Java編程思想讀書筆記

這是一份試圖提綱挈領的讀書筆記,《java編程思想》這本八百多頁的書娓娓道來地包含了太多細節,這對讀者是非常貼心的,我也強烈建議細細讀這本書,如果你希望在短時間內學會java這種語言,那麼這本書不是最好的選擇,你可以看看譚浩強系列。我把看這本書的過程中,個人覺得每一章中最重要的思想、用整理在這裏,希望自己回顧的時候有所參照和提高。也希望大家帶着同樣的目的來看本篇讀書筆記。

Java編程思想讀書筆記

第一章 對象導論

比起過程型語言編寫的程序,用面嚮對象語言編寫的程序更加簡單、易於理解、可複用。《c++編程思想》裏也有這一章,是一個拋磚引自己的玉的章節,不明白可以跳過,回頭再看。

第二章 一切都是對象

java語言裏面,一切都是對象,並且程序員是通過引用來操縱對象。一個簡單的例子,非常輕鬆地讓讀者進入java的世界。需要注意的是java數據會儲存在5個不同的地方:寄存器、堆棧、堆、常量存儲、非ram存儲,用new創建的一般對象都放在堆中,而特殊的基本對象放在堆棧中,如果想把基本對象也放在堆中,需要包裝基本類型。

第三章 操作符

java中的操作符語法類似於c,所以學習起來一點困難也沒有。要特別注意兩個比較大的整數相加或者相乘的時候的溢出問題,用long或者biginteger解決這個問題。

第四章 控制執行流程

我想起《pointer on c》這本書第一章就有這一句話,本書適合那些希望迅速學習一門新語言而不是被“為什麼if和for很重要”的弱智問題耽擱進度的讀者。呵呵,這一章很不厭其煩地介紹了運算、操作符優先級、類型轉換、選擇循環等基本特性,有c或者c++編程經驗的讀者可以大概瀏覽一下。

第五章 初始化和清理

關於初始化:

1.初始化很重要,一定不要忘記。而且java編譯器會很好的防止使用未初始化數據的意外,這是比c和c++更優的地方。

2.編譯器初始化的順序為:

a.類首次加載的時候,有關靜態初始化的所有動作都會執行。

a1.類的加載包括首次創建該類型的對象,或者該類的靜態方法/靜態域首次被訪問

a2.靜態域的初始化在一切初始化之前,即靜態變量散佈在代碼不同的地方,它們也會在任何方法(包括構造器)調用之前被初始化

b.當用new calssname()創建對象的時候,會在堆上開闢足夠的存儲空間,這塊存儲空間被清零,然後執行字段的初始化動作。(這裏的字段初始化都是非靜態的,因為靜態的變量已經在a中執行完畢,而且靜態變量存儲在不同的地方,靜態數據只佔用一份存儲空間)

c.執行構造器

關於清理

c++關於清理的部分包含很大不確定性。目前需要知道的事情是,正常情況下,我們是不需要調用finalize方法的,而且垃圾回收區會自動回收不再使用的對象,同時我們需要自己注意一些需要關閉的文件。

需要注意的是,用=對數組進行“賦值”的時候,實際上是引用的傳遞,就是説,二者指向同一堆。

第六章 訪問權限控制

關於包

你應該有一個自己的域名,這樣發佈你的java程序的時候,就可以將你的包名設置為你的域名倒轉。想要正確讓包工作,要正確設置classpath,對於新手來説,這的確是一個挑戰。我當初就難到了。

關於訪問權限修飾詞

值得注意的是,如果兩個編譯單元放在同一個目錄下並且都沒有設置包名的話,他們對於對方都是擁有包訪問權限的。訪問權限修飾詞是修飾方法和數據,而不是類。類只有兩種訪問權限,包訪問權限或public訪問權限。默認為包訪問權限。如果不希望其它任何人對該類擁有訪問權限,可以把所有的構造器設置為private。但是有一個例外,可以通過該類自己的static成員內部創建(於是就有了工廠設計模式和單例設計模式)。

第七章 複用類

有三種方法複用類:組合,繼承,代理。

組合即是在新的類裏面放上已經定義的類的對象,然後通過調用它的方法來實現自己的功能。

繼承是通過extends關鍵詞繼承某一父類,這樣就能訪問父類的所有public方法(因此為了繼承,一般的規則是將父類的所有數據成員都指定為private,將所有的方法都指定為public)。子類的初始化需要注意的是,(當創建了一個子類的對象時,該對象包含一個基類的子對象)java會在子類的構造器中插入對基類默認構造器的調用。但是如果沒有默認的基類構造器,或者想調用一個帶參數的基類構造器,就必須用關鍵詞super顯式地編寫調用基類構造器的語句,並且配上適當的參數列表。

代理很有意思,(我們姑且使用導出類和基類這樣的字眼,但要清楚我們不是在討論繼承裏面的關鍵詞)在導出類裏保存一個基類的對象,然後用自己的方法對該基類的種種方法進行包裝。

如何決定使用哪種方法複用類呢?is-a就繼承,has-a就用組合。而且,組合比繼承總體上使用更廣泛、代價更小。

向上轉型

這個就牛逼了,第八章,第九章,第十章都與此密切相關。看完本書之後印象最深的就是向上轉型了。

使用final的原因有很多種,一定要弄清楚為什麼使用final,是由於設計還是效率。

final作用於數據的時候:final作用在基本對象比如int上,該值就成為不可改變的,一旦被初始化就無法再被更改,但是作用在普通的對象引用的時候,final使引用恆定不變,但是引用指向的對象是可變的。編譯器需要我們確保final對象一定要被初始化,我們可以通過在構造器中初始化他們,以達到相對自由的效果(稱為空白final,我認為這個名字容易讓人誤解)。java允許在參數列表中以聲明的方式將參數指明為final,這一特性主要用來向匿名內部類傳遞數據(這很重要)。

final作用於方法的時候,説明作者想保持該方法在繼承的過程中不被改變,並且不被覆蓋。同時,被final修飾的方法會被關閉“動態綁定”,這樣編譯器就會為final方法調用生成“有限”有效的代碼。之所以説有限,是因為隨着編譯器的牛逼,它生成的代碼越來越有效。

final作用於類的時候,即是作者聲明對該類的設計不允許任何繼承。

學習得更深入一些,可能對以下事實感到有興趣:java中所有的事物都是對象,每個類的編譯代碼都存在於電腦中的文件夾裏(文件夾的層次根據反轉域名得到),該文件只有在需要使用程序代碼時才被加載。具體的説,就是“類在其任何static成員函數(包括構造函數)被訪問時加載”。第八章 多態

多態的重要基本原理就是向上轉型:繼承允許將對象視為它自己本身的類型或其基類型加以處處理。

將一個方法調用和一個方法主題關聯起來稱為綁定,java中所有的方法都是後期綁定(除了static方法和final方法),所以我們可以編寫只與基類打交道的程序代碼,並且這些代碼對所有的導出類都可以正確運行。

(為什麼static不動態綁定:因為static方法的主要用法就是用類名.方法名這樣的方式來調用,不存在“發送消息給某個對象,讓對象判斷自己怎麼做”這樣的情況。

為什麼final不動態綁定:這是早期final的一種用法,由程序員指定某方法為final,意味着程序員明瞭動態綁定的機制,並且聲明該方法不需要動態綁定,這樣可以獲得更好的性能。這種用法已經很少使用了。)

初始化的時候,導出類的構造函數會自動調用基類的默認構造函數,此過程一直遞歸到最基本的基類。如果需要調用有參數的構造函數就需要手動執行。反過來,如果需要進行清理工作(大部分時候我們都不需要),務必手動執行基類的清理工作先。比如繼承鏈的每個類都實現dispose()方法,那麼執行某個類的清理工作的時候,需要手動調用ose()。不過此種情況下,務必在執行ose()之前釋放成員對象,清理順序與執行順序是相反的。

此外,構造器方面有更加複雜的調用機制,我們不用理它,只需要知道一條有效的準則“用盡可能簡單的方法使對象進入正常狀態,如果可以的話避免調用其它方法”。

java編譯器能夠允許向上多態,就是因為java的機制能保存對象的類型信息,即rtti,正因為這種機制,java編譯器也允許向下轉型,以獲得擴展類的“擴展出”的方法。(另,擴展類“擴展”了方法的這種繼承不是“純繼承”,這樣做好不好?用户自己度量)。向下轉型失敗的話會拋出一個classcastexception。

雖然這一章都是在講多態,但是多態並不總是解決問題最好的方案,它有可能使事情不必要地複雜起來,我們應該總是優先考慮更加靈活的組合。

第九章 接口

一種專門提供“接口”的類叫抽象類,若含有至少一個abstract方法,該類就必須被聲明為abstract的。抽象方法沒有方法體,派生類必須實現它,否則派生類也必須被生命為抽象的。

interface關鍵詞使抽象的概念更進了一步:1.這個“類”完全抽象。2.一個類可以向上轉型為多種interface。要讓一個類遵循某個特定接口,需要使用implement關鍵字。

在這一章中出現了“策略設計模式”這個詞。創建一個能夠根據所傳遞的參數對象的不同而具有不同行為的方法,被稱為策略設計模式。

策略設計模式跟適配器設計模式聯合使用可以提供非常強大的功能,比如我們遇到了無法更改的類(別人編寫的),想要它滿足我們的接口然後放到設計模式裏面去(當然滿足了接口之後的用法就不止如此了),就可以編寫一個適配器,包裝該類同時產生我所需要的接口。

使用抽象類和接口的兩個原因是:1.在多重繼承關係中(這真的很常見,看看java api就知道了),導出類可以被向上轉型為每一個接口。2.防止客户端程序員創建該類的對象。那麼我們該使用抽象類還是接口呢?事實上,如果知道某事物應該成為一個基類,那麼第一選擇應該是使它成為一個接口。

接口之間的繼承能夠形成很好的體系,更像我們的現實生活。但是要特別注意的是,在不同接口中使用相同的方法名通常會造成代碼可讀性的混亂,令人不快。

工廠方法設計模式是又一個重要的設計模式。我們在代碼中增加額外的間接性,一個重要的原因是想要創建框架。