《java編程思想》讀書筆記
這是一份試圖提綱挈領(lǐng)的讀書筆記,《java編程思想》這本八百多頁的書娓娓道來地包含了太多細節(jié),這對讀者是非常貼心的,我也強烈建議細細讀這本書,如果你希望在短時間內(nèi)學(xué)會java這種語言,那么這本書不是最好的選擇,你可以看看譚浩強系列。我把看這本書的過程中,個人覺得每一章中最重要的思想、用整理在這里,希望自己回顧的時候有所參照和提高。也希望大家?guī)е瑯拥哪康膩砜幢酒x書筆記。
第一章 對象導(dǎo)論
比起過程型語言編寫的程序,用面向?qū)ο笳Z言編寫的程序更加簡單、易于理解、可復(fù)用!禼++編程思想》里也有這一章,是一個拋磚引自己的玉的章節(jié),不明白可以跳過,回頭再看。
第二章 一切都是對象
java語言里面,一切都是對象,并且程序員是通過引用來操縱對象。一個簡單的例子,非常輕松地讓讀者進入java的世界。需要注意的是java數(shù)據(jù)會儲存在5個不同的地方:寄存器、堆棧、堆、常量存儲、非ram存儲,用new創(chuàng)建的一般對象都放在堆中,而特殊的基本對象放在堆棧中,如果想把基本對象也放在堆中,需要包裝基本類型。
第三章 操作符
java中的操作符語法類似于c,所以學(xué)習(xí)起來一點困難也沒有。要特別注意兩個比較大的整數(shù)相加或者相乘的時候的溢出問題,用long或者biginteger解決這個問題。
第四章 控制執(zhí)行流程
我想起《pointer on c》這本書第一章就有這一句話,本書適合那些希望迅速學(xué)習(xí)一門新語言而不是被“為什么if和for很重要”的弱智問題耽擱進度的讀者。呵呵,這一章很不厭其煩地介紹了運算、操作符優(yōu)先級、類型轉(zhuǎn)換、選擇循環(huán)等基本特性,有c或者c++編程經(jīng)驗的讀者可以大概瀏覽一下。
第五章 初始化和清理
關(guān)于初始化:
1.初始化很重要,一定不要忘記。而且java編譯器會很好的防止使用未初始化數(shù)據(jù)的意外,這是比c和c++更優(yōu)的地方。
2.編譯器初始化的順序為:
a.類首次加載的時候,有關(guān)靜態(tài)初始化的所有動作都會執(zhí)行。
a1.類的加載包括首次創(chuàng)建該類型的對象,或者該類的靜態(tài)方法/靜態(tài)域首次被訪問
a2.靜態(tài)域的初始化在一切初始化之前,即靜態(tài)變量散布在代碼不同的地方,它們也會在任何方法(包括構(gòu)造器)調(diào)用之前被初始化
b.當(dāng)用new calssname()創(chuàng)建對象的時候,會在堆上開辟足夠的存儲空間,這塊存儲空間被清零,然后執(zhí)行字段的初始化動作。(這里的字段初始化都是非靜態(tài)的,因為靜態(tài)的變量已經(jīng)在a中執(zhí)行完畢,而且靜態(tài)變量存儲在不同的地方,靜態(tài)數(shù)據(jù)只占用一份存儲空間)
c.執(zhí)行構(gòu)造器
關(guān)于清理
c++關(guān)于清理的部分包含很大不確定性。目前需要知道的事情是,正常情況下,我們是不需要調(diào)用finalize方法的,而且垃圾回收區(qū)會自動回收不再使用的對象,同時我們需要自己注意一些需要關(guān)閉的文件。
需要注意的是,用=對數(shù)組進行“賦值”的時候,實際上是引用的傳遞,就是說,二者指向同一堆。
第六章 訪問權(quán)限控制
關(guān)于包
你應(yīng)該有一個自己的域名,這樣發(fā)布你的java程序的時候,就可以將你的包名設(shè)置為你的域名倒轉(zhuǎn)。想要正確讓包工作,要正確設(shè)置classpath,對于新手來說,這的確是一個挑戰(zhàn)。我當(dāng)初就難到了。
關(guān)于訪問權(quán)限修飾詞
值得注意的是,如果兩個編譯單元放在同一個目錄下并且都沒有設(shè)置包名的話,他們對于對方都是擁有包訪問權(quán)限的。訪問權(quán)限修飾詞是修飾方法和數(shù)據(jù),而不是類。類只有兩種訪問權(quán)限,包訪問權(quán)限或public訪問權(quán)限。默認為包訪問權(quán)限。如果不希望其它任何人對該類擁有訪問權(quán)限,可以把所有的構(gòu)造器設(shè)置為private。但是有一個例外,可以通過該類自己的static成員內(nèi)部創(chuàng)建(于是就有了工廠設(shè)計模式和單例設(shè)計模式)。
第七章 復(fù)用類
有三種方法復(fù)用類:組合,繼承,代理。
組合即是在新的類里面放上已經(jīng)定義的類的對象,然后通過調(diào)用它的方法來實現(xiàn)自己的功能。
繼承是通過extends關(guān)鍵詞繼承某一父類,這樣就能訪問父類的所有public方法(因此為了繼承,一般的規(guī)則是將父類的所有數(shù)據(jù)成員都指定為private,將所有的方法都指定為public)。子類的初始化需要注意的是,(當(dāng)創(chuàng)建了一個子類的對象時,該對象包含一個基類的子對象)java會在子類的構(gòu)造器中插入對基類默認構(gòu)造器的調(diào)用。但是如果沒有默認的基類構(gòu)造器,或者想調(diào)用一個帶參數(shù)的基類構(gòu)造器,就必須用關(guān)鍵詞super顯式地編寫調(diào)用基類構(gòu)造器的語句,并且配上適當(dāng)?shù)膮?shù)列表。
代理很有意思,(我們姑且使用導(dǎo)出類和基類這樣的字眼,但要清楚我們不是在討論繼承里面的關(guān)鍵詞)在導(dǎo)出類里保存一個基類的對象,然后用自己的方法對該基類的種種方法進行包裝。
如何決定使用哪種方法復(fù)用類呢?is-a就繼承,has-a就用組合。而且,組合比繼承總體上使用更廣泛、代價更小。
向上轉(zhuǎn)型
這個就牛逼了,第八章,第九章,第十章都與此密切相關(guān)?赐瓯緯笥∠笞钌畹木褪窍蛏限D(zhuǎn)型了。
使用final的原因有很多種,一定要弄清楚為什么使用final,是由于設(shè)計還是效率。
final作用于數(shù)據(jù)的時候:final作用在基本對象比如int上,該值就成為不可改變的,一旦被初始化就無法再被更改,但是作用在普通的對象引用的時候,final使引用恒定不變,但是引用指向的對象是可變的。編譯器需要我們確保final對象一定要被初始化,我們可以通過在構(gòu)造器中初始化他們,以達到相對自由的效果(稱為空白final,我認為這個名字容易讓人誤解)。java允許在參數(shù)列表中以聲明的方式將參數(shù)指明為final,這一特性主要用來向匿名內(nèi)部類傳遞數(shù)據(jù)(這很重要)。
final作用于方法的.時候,說明作者想保持該方法在繼承的過程中不被改變,并且不被覆蓋。同時,被final修飾的方法會被關(guān)閉“動態(tài)綁定”,這樣編譯器就會為final方法調(diào)用生成“有限”有效的代碼。之所以說有限,是因為隨著編譯器的牛逼,它生成的代碼越來越有效。
final作用于類的時候,即是作者聲明對該類的設(shè)計不允許任何繼承。
學(xué)習(xí)得更深入一些,可能對以下事實感到有興趣:java中所有的事物都是對象,每個類的編譯代碼都存在于電腦中的文件夾里(文件夾的層次根據(jù)反轉(zhuǎn)域名得到),該文件只有在需要使用程序代碼時才被加載。具體的說,就是“類在其任何static成員函數(shù)(包括構(gòu)造函數(shù))被訪問時加載”。
第八章 多態(tài)
多態(tài)的重要基本原理就是向上轉(zhuǎn)型:繼承允許將對象視為它自己本身的類型或其基類型加以處處理。
將一個方法調(diào)用和一個方法主題關(guān)聯(lián)起來稱為綁定,java中所有的方法都是后期綁定(除了static方法和final方法),所以我們可以編寫只與基類打交道的程序代碼,并且這些代碼對所有的導(dǎo)出類都可以正確運行。
(為什么static不動態(tài)綁定:因為static方法的主要用法就是用類名.方法名這樣的方式來調(diào)用,不存在“發(fā)送消息給某個對象,讓對象判斷自己怎么做”這樣的情況。
為什么final不動態(tài)綁定:這是早期final的一種用法,由程序員指定某方法為final,意味著程序員明了動態(tài)綁定的機制,并且聲明該方法不需要動態(tài)綁定,這樣可以獲得更好的性能。這種用法已經(jīng)很少使用了。)
初始化的時候,導(dǎo)出類的構(gòu)造函數(shù)會自動調(diào)用基類的默認構(gòu)造函數(shù),此過程一直遞歸到最基本的基類。如果需要調(diào)用有參數(shù)的構(gòu)造函數(shù)就需要手動執(zhí)行。反過來,如果需要進行清理工作(大部分時候我們都不需要),務(wù)必手動執(zhí)行基類的清理工作先。比如繼承鏈的每個類都實現(xiàn)dispose()方法,那么執(zhí)行某個類的清理工作的時候,需要手動調(diào)用super.dispose()。不過此種情況下,務(wù)必在執(zhí)行super.dispose()之前釋放成員對象,清理順序與執(zhí)行順序是相反的。
此外,構(gòu)造器方面有更加復(fù)雜的調(diào)用機制,我們不用理它,只需要知道一條有效的準則“用盡可能簡單的方法使對象進入正常狀態(tài),如果可以的話避免調(diào)用其它方法”。
java編譯器能夠允許向上多態(tài),就是因為java的機制能保存對象的類型信息,即rtti,正因為這種機制,java編譯器也允許向下轉(zhuǎn)型,以獲得擴展類的“擴展出”的方法。(另,擴展類“擴展”了方法的這種繼承不是“純繼承”,這樣做好不好?用戶自己度量)。向下轉(zhuǎn)型失敗的話會拋出一個classcastexception。
雖然這一章都是在講多態(tài),但是多態(tài)并不總是解決問題最好的方案,它有可能使事情不必要地復(fù)雜起來,我們應(yīng)該總是優(yōu)先考慮更加靈活的組合。
第九章 接口
一種專門提供“接口”的類叫抽象類,若含有至少一個abstract方法,該類就必須被聲明為abstract的。抽象方法沒有方法體,派生類必須實現(xiàn)它,否則派生類也必須被生命為抽象的。
interface關(guān)鍵詞使抽象的概念更進了一步:1.這個“類”完全抽象。2.一個類可以向上轉(zhuǎn)型為多種interface。要讓一個類遵循某個特定接口,需要使用implement關(guān)鍵字。
在這一章中出現(xiàn)了“策略設(shè)計模式”這個詞。創(chuàng)建一個能夠根據(jù)所傳遞的參數(shù)對象的不同而具有不同行為的方法,被稱為策略設(shè)計模式。
策略設(shè)計模式跟適配器設(shè)計模式聯(lián)合使用可以提供非常強大的功能,比如我們遇到了無法更改的類(別人編寫的),想要它滿足我們的接口然后放到設(shè)計模式里面去(當(dāng)然滿足了接口之后的用法就不止如此了),就可以編寫一個適配器,包裝該類同時產(chǎn)生我所需要的接口。
使用抽象類和接口的兩個原因是:1.在多重繼承關(guān)系中(這真的很常見,看看java api就知道了),導(dǎo)出類可以被向上轉(zhuǎn)型為每一個接口。2.防止客戶端程序員創(chuàng)建該類的對象。那么我們該使用抽象類還是接口呢?事實上,如果知道某事物應(yīng)該成為一個基類,那么第一選擇應(yīng)該是使它成為一個接口。
接口之間的繼承能夠形成很好的體系,更像我們的現(xiàn)實生活。但是要特別注意的是,在不同接口中使用相同的方法名通常會造成代碼可讀性的混亂,令人不快。
工廠方法設(shè)計模式是又一個重要的設(shè)計模式。我們在代碼中增加額外的間接性,一個重要的原因是想要創(chuàng)建框架。
【《java編程思想》讀書筆記】相關(guān)文章:
Java編程開發(fā)簡介08-17
Java基本編程技巧11-16
關(guān)于JAVA的XML編程10-08
Java編程常見問題匯總08-22
Java中的動態(tài)代碼編程08-15
JAVA編程面試題及答案09-16
java面向?qū)ο缶幊填}庫及答案11-14