《HEAD FIRST JAVA》第一次回顧和整理

第一章 進(jìn)入Java的世界(基本概念)

主要介紹了Java的工作原理,發(fā)展簡史,程序結(jié)構(gòu)和一些簡單的語法。學(xué)過其他語言的人表示這章完全沒有壓力。

1, 程序的層次:源文件(source file)->類(class)->方法(methods)。

2, Java里面integer和boolean不相容。

3, 語法與C差不多,不過作者好像一直很反感拿C與Java作比較。

第二章 拜訪對象村(類與對象)

一開始用了一個巨冷的故事來闡述面向過程編程與面向?qū)ο缶幊痰牟顒e(結(jié)果當(dāng)然是面向?qū)ο髢?yōu)勝= =先保留意見吧)。

1, 繼承機(jī)制使子類可以通過繼承父類代碼來減少重復(fù)代碼,覆蓋機(jī)制使子類在不必改動父類的同時可以選擇實現(xiàn)自己的方法。(這個機(jī)制太強(qiáng)大了?。?/p>

2, 類是繪制對象的藍(lán)圖,而對象是已知的事物加上執(zhí)行的動作。對應(yīng)著,類包括實例變量(instance variable)和方法(methods)。

3, Java程序執(zhí)行期間是一組可以相互調(diào)用或交流信息的對象,對象之間有著獨立性(對象自治)。

4, main()在java里面的作用:測試真正的類和啟動Java應(yīng)用程序。Java是面向?qū)ο蟮木幊蹋詍ain()里面基本是不帶任何方法的,僅作為測試用和啟動用。

第三章 認(rèn)識變量(primitive主數(shù)據(jù)類型和引用)

介紹了primitive類型變量和引用變量,并闡述了之前的差別。

1, 變量必須有變量類型,兩性類型與類之間有時是共通的,所以一般有著相同的命名規(guī)則(如果可能的話,每個單詞的首字母都要大些,區(qū)分于變量名稱的命名:除了第一個單詞首字母要小寫外,之后的單詞的首字母都要大寫)。

2, 變量名稱必須以字母,_或&開頭(不能以數(shù)字開頭)。

3, 除非加上“f”,否則所有帶小數(shù)點的值在Java里面都看作double類型。

4, Primitive主數(shù)據(jù)類型變量值是該值的字節(jié)所表示的。

5, 引用變量類似于指針,儲存的是引用對象的地址(儲存方式)。

6, 圓點運算符(.)表示“取得圓點前面的對象,然后求出該對象在圓點后面的事物”。

7, 當(dāng)一個對象失去所有的引用變量時,它就完蛋了。

8, 數(shù)組是對象,無論它里面裝的是不是primitive類型。

第四章 對象的行為(方法操作實例變量)

一開始那張圖片,我每次看到都想笑(那貨的表情和動作都太到位了= =后面一頁的*號冷笑話也很強(qiáng)大~)??瓤?,這章主要是圍繞對象的方法來闡述一些拓展技巧。

1, 根據(jù)傳入的實參(arguments)或者對象的實例變量(instance variable)的不同,同一個方法在同類型的不同的對象可以有著不同的表現(xiàn)形式。

2, 實參(arguments)是傳給方法的實際值,傳入方法后就變成了形參。形參(parameters)與局部變量(local)類似是一樣的。改變形參并不改變實參。(跟C一樣)傳入與返回的參數(shù)的值的類型可以隱含地放大或者明確地縮小。

3, 可以從方法里面返回值,聲明了返回最好要返回(我敲代碼時發(fā)覺時聲明了返回不返回會報錯的,但P78最后一個問題的回答并不是這樣的??囧),一般情況下只能返回一個值,但是可以返回一個數(shù)組,再深一層的,可以返回ArrayList,換言之,只要你封裝好了,可以返回任意數(shù)量任意類型的任意變量的任意組合。(這也太強(qiáng)大了吧???)

4, Java是傳值調(diào)用(pass by value),如果調(diào)用的實參是個引用變量,同樣拷貝之。

5, 用setter(mutator)和getter(accessor)進(jìn)行封裝(encapsulation),可以保證對象的實例變量可以通過設(shè)置setter來防止被惡搞。(用private設(shè)置實例變量,用public來設(shè)置setter和getter)這樣讀取和更改實例變量的效率會變低,不過能夠提高程序的抵抗力抗性和恢復(fù)力抗性。

6, 實例變量有默認(rèn)值(整形為0,浮點型為0.0,布爾型為false),局部變量沒有默認(rèn)值,使用前需要初始化。

7, 使用==來比較兩個primitive主數(shù)據(jù)類型或者兩個引用是否引用到同一個對象。使用equals()來判斷兩個對象是否在意義上相等。(關(guān)于“在意義上”的概念需要斟酌,目前主要用于比較String類型是否相等)。

第五章 超強(qiáng)力方法(編寫程序)

通過設(shè)計一個SimpleDotComGame大致地說明了程序設(shè)計與實現(xiàn)的步驟。

1, 程序設(shè)計的第一步是高層設(shè)計,把程序的基本架構(gòu)抽象出來。(想起了萬惡的NS圖)

2, 第二步,根據(jù)基本架構(gòu)來構(gòu)思需要什么對象,需要實現(xiàn)什么類。(這是與面向過程不一樣的地方,但某程度上類的方法有點像面向過程中的過程函數(shù)的一部分,Java優(yōu)勝在那強(qiáng)大的類的獨立性)。書本上提議開發(fā)類的過程是:找出類應(yīng)該做的事情->列出實例變量和方法->編寫方法的偽代碼->編寫方法的測試用程序->實現(xiàn)類->測試方法->出錯或重新設(shè)計->邀請辣妹參加慶功派對(= =這什么?。浚?/p>

3, 偽碼,描述要做什么而不是怎么做的類文字,書上的偽碼都是全英文的,壓力很大,不過估計以后也要習(xí)慣了,因為感覺上計算機(jī)方面比較好的書都是外國的。測試碼,寫在真實碼之前(因為真實碼都寫出來了估計就沒動力寫測試碼了),目的是為了寫好真實碼之后測試真實碼。

4, 書本后面介紹了幾個技巧:加強(qiáng)版的for(要先把環(huán)境參數(shù)調(diào)到1.5以上才能用);把字符串轉(zhuǎn)換成整形的Integer.parseInt(String);還有C里面學(xué)習(xí)過的后遞增和break語句。

第六章 使用Java函數(shù)庫 (認(rèn)識Java的API)

這章的頁數(shù)很多,把第五章的游戲排BUG之后又升級到高級版(依然無界面)。之后介紹了Java API的用途和用法。

1,排BUG過程中書本引入了強(qiáng)大ArrayList對象,這個對象很牛地,有著類似數(shù)組的簡易操作性的同時有著類似鏈表的動態(tài)伸縮性,代價是它耗費的資源多一點。(對于add(index, Object)這個方法,index的值與之前的值不能跳空)

2,制作高級版時,書本用一堆球和杯子加遙控器的組合強(qiáng)調(diào)了Java是個面向?qū)ο蟮木幊坦ぞ摺?/p>

3,接著寫到了一些布爾表達(dá)式的運算符,跟C一樣,所以沒有壓力。

4, Java API中類是被包裝在包中的;使用是必須使用import或者在出現(xiàn)的每個位置寫出全稱(除了java.lang包中的類);關(guān)于java和javax的趣聞;關(guān)于查詢API給出了查閱參考書和查閱HTML API文檔(真希望能具體點)。

第七章 對象村的優(yōu)質(zhì)生活(繼承與多態(tài))

我認(rèn)為繼承和覆蓋是前十二章里面Java里面最強(qiáng)大的機(jī)制,拓展性,獨立性,適應(yīng)性,易改性???多態(tài)什么的就是為了配合這個強(qiáng)大的機(jī)制而存在的。

1, 關(guān)于方法的繼承(inheritance)與覆蓋(override),書上說得是很清楚的,子類可以繼承父類所有的非私有方法,也可以通過寫出同名同參數(shù)的方法來覆蓋父類的方法。方法調(diào)用時,遵循低階優(yōu)先原則。關(guān)于方法繼承,有一點要分辨清楚的,子類繼承了父類的方法,與把父類的方法的代碼拷貝一份到子類的代碼中的意義是不一樣的,當(dāng)其他對象引用該方法時,前者會跳入父類中進(jìn)行調(diào)用,后者會跳入子類中進(jìn)行調(diào)用(因為方法已經(jīng)被覆蓋了)。兩者的主要差別是如果兩者有著同名的實例變量,方法中又涉及了該實例變量,就會產(chǎn)生不同的結(jié)果。即使它們共用同一個實例變量,這點上的模糊也通常會導(dǎo)致方法返回一個跟預(yù)想不一樣的值或者產(chǎn)生一個預(yù)料未及的結(jié)果。關(guān)于實例變量的繼承與覆蓋,書上說得一般清楚,所以后來編碼這一直弄得我好糾結(jié)?,F(xiàn)在稍微清晰了一點,但也不保證我的理解是正確的,寄希望于下一本教材吧。上機(jī)操作后,我感覺“覆蓋”這個概念對于實例變量來說不適用,“繼承”還有有那點意思的,若子類里面沒有新建同名的實例變量,類似于方法的繼承,同樣不能理解成把父類的關(guān)于實例變量的代碼拷貝一份到子類中去,調(diào)用時,依然是通過調(diào)用父類的實例變量。而當(dāng)子類中存在父類的同名實例變量時,不會產(chǎn)生覆蓋,而且作為兩個毫不相干的變量各自獨自地存在于所屬的類中,調(diào)用的時候根據(jù)引用的不同來區(qū)分。

2, 設(shè)計繼承樹的步驟:找出具有共同屬性和行為的對象(用繼承來防止子類中出現(xiàn)重復(fù)的程序代碼)->設(shè)計代表共同狀態(tài)與行為的類 ->決定子類時候需要讓某項行為(也就是方法的實現(xiàn))有著特定不同的運作方式->通過尋找使用共同行為的子類來找出更多抽象化的機(jī)會->完成類的繼承層次。

3, 判斷選擇繼承還是看作實例變量的方法:“是一個”(IS-A)和“有一個”(HAS-A)。

4, 一些關(guān)于方法繼承的細(xì)節(jié):繼承單向性(因而有了IS-A的單向性),父類無法繼承子類的方法;子類中可以用super()來引用父類的方法;public類型的成員會被繼承,private類型的成員不會被繼承;x extends y && y extends z ---> x extends z,就是說,x可以通過z的IS-A測試;繼承可以減少重復(fù)代碼,當(dāng)要修改方法時,只要父類的參數(shù)沒有改變,子類都不需要改動就能直接繼承;繼承定義出共同的協(xié)議,也就是說,繼承可以確保某個父類之下所有子類都會有父類所持有的全部可繼承方法;可以用final來標(biāo)記類使它或者把里面的實例變量和方法標(biāo)記成private來拒絕被繼承;在不知道父類源代碼僅知道其方法關(guān)鍵字的時候,可以通過繼承的方法來設(shè)計功能有所延展的子類。

5, 多態(tài)(polymorphism):當(dāng)定義一組類的父型時,可以用子型的任何類來填補(bǔ)任何需要或期待父型的位置。換句話說,運用多態(tài)時,引用類型可以是實際對象類型的父類,這樣的話,參數(shù)和返回類型都可以多態(tài)化處理。其中有一點是要特別注意的,當(dāng)一個對象實質(zhì)是子類但它的引用對象是子類的父類時,雖然它本質(zhì)是子類但它卻不能調(diào)用子類中的任何東西,Java看重的是引用類型,也就是說此對象只能引用父型中的東西,但可以通過用子類的強(qiáng)制轉(zhuǎn)換符來把引用轉(zhuǎn)換成子類。

6, 最后談?wù)劯采w和重載,子類同名方法未必就能覆蓋掉父類的方法:連參數(shù)類型和數(shù)目都相同時叫覆蓋,稍有不同就叫重載。重載之間毫無聯(lián)系,各自獨立存在,JVM會根據(jù)參數(shù)的差別自行決定調(diào)用哪個重載的方法。最后是關(guān)于覆蓋和重載的一些細(xì)節(jié)上的區(qū)分:覆蓋(override),參數(shù)必須要一樣,其返回類型必須要兼容;不能降低方法的存取權(quán)限。重載(overload),返回類型可以不同;不能只改變返回類型(參數(shù)在類型和數(shù)目上至少要稍有不同);可以更改存取權(quán)限(因為相互獨立)。

第八章 深入多態(tài)(接口與抽象類)

這章繼續(xù)討論多態(tài),書上說沒有接口活不下去,現(xiàn)在有點體會。Java子類有時候扮演著不同的角色,這時候就需要用到接口了,因為父類只能有一個,但是接口的話就沒有這個限制了。

1,抽象類(abstract class):有一些類在理論上是不應(yīng)該被初始化的,這時候加上abstract關(guān)鍵字可以防止它被new出來。抽象類的作用就是在防止被初始化之余能被繼承以維持多態(tài)。(*書上提到特例:抽象類可以有static成員,目前不明白)。抽象類必須要被extends。

2,抽象的方法:抽象的方法沒有實體,因而一定要被覆蓋,即必須要實現(xiàn)所有抽象的方法。當(dāng)聲明了一個抽象的方法時,該類必須標(biāo)記成抽象類(我理解成這是要通過強(qiáng)迫設(shè)置子類繼承來實現(xiàn)方法的覆蓋)。

3,萬用類Object:所有類的父類;書上介紹的四個方法:equals(),hashCode(),getClass(),toString();Object的作用是為多態(tài)提供一個萬能模板,因而同樣要注意到Object類型的變量只能做Object類里面的方法,要使用子類的方法,只能通過強(qiáng)制轉(zhuǎn)換符(再次強(qiáng)調(diào)Java很注重引用變量的類型:“編譯器是根據(jù)引用類型來判斷有哪些method可以調(diào)用,而不是根據(jù)Object確實的類型?!保?;而理所當(dāng)然地,任何對象都可以使用Object里面的方法。

4,書本再再再次強(qiáng)調(diào)了Java很注重引用變量的類型:只能在引用變量的類確實有該方法才能夠調(diào)用它;把類的公有方法當(dāng)做是合約的內(nèi)容,合約是你對其他程序的承諾協(xié)議。

5, 接口(interface):本質(zhì)上是一個公用的且里面都是抽象的方法的抽象類。目的是為了讓對象從單一的父子類關(guān)系中得到拓展以在保持對象獨立性和脈絡(luò)清晰性的同時得到多重身份。一言蔽之,接口就是為多態(tài)而存在的(不知這樣說會不會太絕對呢= =)。接口可以跨越不同的繼承樹進(jìn)行延展,同一對象也可以接上任意的接口。

第九章 對象的前世今生(構(gòu)造器與垃圾收集器)

這章的冷笑話和配圖是前九章里面最到位的一章,- -吐槽乏力了??正如標(biāo)題所言,這張說的是構(gòu)造器(constructors)和垃圾收集器(garbage collection)。

1,關(guān)于生存空間和生存周期(life)和作用域(scope)什么的,學(xué)過C的表示沒有壓力。所有的對象生存在堆(heap)中,方法調(diào)用和局部變量生存在棧(stack)上,而實例變量是生存在其依附的對象上,即也屬于堆中。關(guān)于棧,遵循后進(jìn)先出原則,關(guān)于各種引用變量,局部引用變量存在于棧,實例引用變量存在于堆,儲存的自然只是存取方式。

2,構(gòu)造函數(shù)(constructor):一項關(guān)鍵特征是它不會有返回類型(包括void),另一項關(guān)鍵特征是它會在對象能后被賦值給引用之前就執(zhí)行。一些構(gòu)造函數(shù)的應(yīng)用細(xì)節(jié):可以使用構(gòu)造函數(shù)來初始化對象的實例變量,如果有提供默認(rèn)值的要求,還可以通過重載構(gòu)造函數(shù)來滿足,而且最后在無參數(shù)的構(gòu)造函數(shù)中設(shè)定一個默認(rèn)值;編譯器會幫你自動補(bǔ)全,前提是你沒有寫任何一個構(gòu)造函數(shù)。

3,構(gòu)造函數(shù)與父類之間的關(guān)系,這個確實有點糾結(jié):由于子類都包含了父類的實例變量,所以當(dāng)子類的繼承函數(shù)執(zhí)行前,必須先執(zhí)行父類的繼承函數(shù),直至最后執(zhí)行Object的構(gòu)造函數(shù),這個過程成為“構(gòu)造函數(shù)鏈”(constructor chaining);調(diào)用父類的構(gòu)造函數(shù)用super(),調(diào)用類中的重載構(gòu)造函數(shù)用this(),而由于super()和this()語法上都要求放在構(gòu)造函數(shù)的第一行,所以它們不能同時使用。

4,關(guān)于垃圾收集器的工作機(jī)理:當(dāng)對象失去最后一個引用變量時,它失去存在的意義,等待的就是被回收的命運。關(guān)于引用變量的生存周期,局部引用變量生存與方法當(dāng)中,方法結(jié)束,引用就消失;實例引用變量的生存周期與它存在的類的生存周期一樣,換句話說,他倆的生死大權(quán)在類的引用變量上,死去的方法有“引用永久性的離開它的范圍”“引用被賦值到其他的對象中”“直接將引用設(shè)定為null”。

第十章 數(shù)字很重要(數(shù)字和靜態(tài))

靜態(tài)什么的到現(xiàn)在依然不是很理解,很頭痛。介紹完靜態(tài)之后就是一些對數(shù)字,格式化,日期等之流的介紹,大概瀏覽了下。

1, 靜態(tài)的方法通常是實用的方法,不依賴對象的實例變量(可理解成語句獨立性很強(qiáng),不依賴前后的語句),因而不需要建立對象(并且通常構(gòu)造函數(shù)私有化來阻止用戶創(chuàng)建實例)。引用時用類的名字來引用即可。又因為靜態(tài)方法引用對象的是類,所以靜態(tài)方法是不可及調(diào)用同一個類中的非靜態(tài)的實例變量(因為無法識別應(yīng)該調(diào)用那個對象的的變量,類似的理由,靜態(tài)方法也不能調(diào)用同一個類中非靜態(tài)方法),只可以調(diào)用靜態(tài)實例變量(因為同類的對象共享同一個靜態(tài)實例對象,不存在混淆的問題)

2, 靜態(tài)變量具有共享的特性,在類被加載時初始化(優(yōu)先于構(gòu)造函數(shù),并在所有靜態(tài)方法開始前初始化)。如果即將運行靜態(tài)方法前還沒有賦初值,自動設(shè)為默認(rèn)值,整形為0,浮點型為0.0,布爾型為false,引用變量為null。

3, Java中的常數(shù):用public static final來修飾,即具有“公用”“免實例”“不變”的特性。

4, final:用于變量時,變量不可改變值(定義時貌似必須初始化);用于方法時,方法無法被覆蓋;用于類時,類無法被繼承。名副其實的終結(jié)者。(注:final的類沒必要再定義final的方法,無法繼承根本不存在方法被覆蓋的問題。)

5, primitive主數(shù)據(jù)類型的包裝:1.5之后有了自動包裝和解包(autoboxing),一切都變得很美好?;究梢詿o視int和Integer的差別了,直接套用就是了,強(qiáng)大無比的實。用性。(目前發(fā)現(xiàn)不可套用的是ArrayList中的contains方法,需要用到強(qiáng)制轉(zhuǎn)換符。)后面提到了包裝的實用性方法:parseInt(),parseDouble(),booleanValue(),toString()等。

6, 數(shù)字的格式化:學(xué)過C的表示繼續(xù)沒有壓力。%[argument number][flags][width][.precision]type這個寫得好專業(yè)就收錄下來了,其他看書OK。

7, 日期的表示法和計算法:這個看書吧= =(import java.util.Date;import java.util.Calendar)

8, 最后一點,靜態(tài)的import,這個我覺得作用不大,為少翹一點代碼而降低程序的易讀性很不劃算。

第十一章 有風(fēng)險的行為(異常處理)

開始介紹如何編寫軟件,很激動~這章主要說異常處理(exception handling)和MIDI(musical instrument digital interface)播放相關(guān)。

1, 異常處理:除了RuntimeException和它的子類(一般是可以在編譯階段排除的語法錯誤),其他異常(exception)都要進(jìn)行處理(或者duck掉給調(diào)用者處理)。處理方法使用try{}和catch{}語句。(選擇性加上finally{},兩者至少要有一個。)如果不想在當(dāng)前處理,可以用throws標(biāo)識方法來duck給此方法的調(diào)用者,調(diào)用者也可以進(jìn)一步duck給上一級調(diào)用者。如果連main()函數(shù)也ducking,那么JVM就會死掉。一些細(xì)節(jié):try的時候遇到異常后立即跳到catch(如果有的話),否則運行finally(如果有的話),之后拋出錯誤(如果有throws后綴的話);一個try后面可以多個catch,平行關(guān)系的異常,可以不管先后順序,父子關(guān)系的異常,子型放在父型之上。

2, MIDI(import javax.sound.midi.*;):本身不帶有音樂信息,上面帶的是如何播放音樂的信息,跟樂譜差不多,所以占用空間很小。播放音樂的層次:Sequencer(播放器)->Sequence(CD盤)->Track(單曲)->MidiEvent(音符)。構(gòu)建的五個步驟:取得Sequencer并將它打開->創(chuàng)建新的Sequence->從Sequence中創(chuàng)建新的Track->填入MidiEvent并讓Sequencer播放->按下play鍵。然后是各種的方法和各種的參數(shù),各種看書和查閱JAVA API(MIDI的參數(shù)表至今沒有找到)。

第十二章 看圖說故事(圖形用戶接口)

這章主要介紹了GUI(Graphical User Interface):制作窗口和按鈕,簡單繪圖和貼圖,簡單的動畫等等。

1,JFrame用于創(chuàng)建主框架,通過getContentPane()把JButton,JLabel等其他組件(widget)掛載在上面。(import javax.swing.*;其他方法和參數(shù)見書本或JAVA API)

2,事件源(event source)本身是個對象(框架,按鈕,滾動條等),把用戶的操作(點擊鼠標(biāo),按鍵等)轉(zhuǎn)換成事件(event),如果當(dāng)前事件源被一個或若干個監(jiān)聽器(listener)注冊,那么它會把事件(event object)當(dāng)成參數(shù)返回到實現(xiàn)了對應(yīng)的監(jiān)聽接口的對象上面。

3, 通過用子類繼承JPanel來掛圖和繪圖。掛圖和繪圖在類里面的paintComponent方法里面實現(xiàn)。繪圖的時機(jī)一般由系統(tǒng)決定,也可以通過repaint()命令來強(qiáng)制馬上重繪。

4, 內(nèi)部類(inner class):唯一綁定在第一個初始化自己的外部類上,綁定后不可更改綁定對象,可以使用外部所有的方法與變量,包括有私有標(biāo)識的。

5, Thread.sleep()用于短暫掛起線程。(C里面的Sleep()函數(shù)??)

6, 監(jiān)聽MIDI文件的方法:注冊一個特殊編號的MIDI事件(看作ControllerEvent)插入到MIDI文件上所有含有NOTE ON(第一個參數(shù)是144)標(biāo)志的節(jié)拍上,把ControllerEventListener注冊到sequence上,最后在帶有ControllerEventListener()接口的controlChange(ShortMessage ev)方法上實現(xiàn)監(jiān)聽后的響應(yīng)工作。

第十三章 運用Swing(Swing)

篇幅比較短的一章,主要介紹了布局管理器(Layout Managers)。

1, 幾乎所有組件(Components,或widget)都能夠安置其他的組件,除了JFrame之外,交互組件于背景組件的差異不明顯(JPanel雖然一般都當(dāng)做背景來使用,但也可以像按鈕一樣注冊鼠標(biāo)點選的事件)

2, 布局管理器(Layout Managers):通過一種交互的機(jī)制(人機(jī)交互,布局層次內(nèi)部的交互)自主決策組件布局的一類對象。決策時優(yōu)先遵循自己的布局策略,在不破壞自身布局策略的前提下最大程序上滿足用戶提出的布局請求(也就是有時候會違反用戶的請求)。

3, 書上提到的三大布局管理器:BorderLayout(把背景組件分成東南西北中五個區(qū)域,優(yōu)先分配南北,然后東西,最后剩下的部分為中間),F(xiàn)lowLayout(把組件從左到右地排列,并有自動換行的機(jī)制),BoxLayout(把組件從上到下地排列,但不帶有自動換行的機(jī)制)

4, 剩下的JTextArea,JScrollerPane等的方法和參數(shù)等可參看書本。

第十四章 保存對象(序列化和文件輸入/輸出)

終于到輸入輸出了,這一章的翻譯挺不到位,建議對照英文教材閱讀之。

1, Java數(shù)據(jù)輸出的兩種方法,只給Java讀取的話用序列化(serialization),如果要給其他程序讀取或使用,輸出純文本文件。

2, (import java.io;)一般來說,串流(stream)要連接流(connection stream)和鏈接流(chain stream)兩兩配合才能有效。其中連接流負(fù)責(zé)連接到文件,socket等,但因為自身一般只有像輸出字節(jié)等低級方法,所以要借助較為高級的連接流中的高級方法才能轉(zhuǎn)換成功。

3, 要一個類實現(xiàn)可序列化,需要實現(xiàn)Serializable接口。如果不想某個實例變量被序列化,標(biāo)記上transient(像網(wǎng)絡(luò)聯(lián)機(jī)這類隨機(jī)數(shù)據(jù)也應(yīng)該標(biāo)記transient),考慮到要完整且正確地恢復(fù)到原狀態(tài)(所謂狀態(tài),一般就是指實例變量的值),序列化時候需要把與保存對象相關(guān)的所有對象形成的網(wǎng)絡(luò)全部序列化保存(如果網(wǎng)絡(luò)中有一部分實例變量既沒有實現(xiàn)Serializable又沒有被標(biāo)記transient)。

4, 對于純文件的處理用FileWriter和FileReader,為提高效率,可以選擇使用BufferedReader和BufferedWriter

5, 剩下還有關(guān)于GUI和IO的很多類很多方法很多參數(shù),參看書本吧。

第十五章 網(wǎng)絡(luò)聯(lián)機(jī)(網(wǎng)絡(luò)與線程)

嘛,這章大致介紹了怎么實現(xiàn)網(wǎng)絡(luò)聯(lián)機(jī),還是就是一些多線程的細(xì)節(jié)問題。

1, 聊天程序的工作方式:客戶端連接到服務(wù)器->服務(wù)器建立連接并把客戶端架到來并清單中->另外一個用戶連接上來->用戶A送出信息到聊天服務(wù)器上->服務(wù)器將信息送給所有的來賓(一開始對最后一步有疑問,參看P488就恍然大悟了)

2, Java不需要注意太多細(xì)節(jié)的東西就可以架設(shè)好網(wǎng)絡(luò)連接(同時譯者提醒讀者不要把架設(shè)網(wǎng)絡(luò)想成是太簡單的事情- -)

3, (import java.net.*;)建立socket連接,要知道IP地址和TCP的端口號。(本機(jī)IP地址為:127.0.0.1)

4, 關(guān)于網(wǎng)絡(luò)串流的讀寫:讀,服務(wù)器(server)->Socket輸入流->InputStreamReader->BufferedReader->客戶端(client)。寫,客戶端->PrintWriter->Socket輸出流->服務(wù)器。(不知道為什么中間不加BufferedWriter)

5, 多線程(multithreading):線程(thread)是一種獨立的執(zhí)行空間(a separate call stack),除非是多處理器,否則新線程并不是單獨運行的線程,雖然感覺上是這樣。

6, 每個thread需要一個任務(wù)來執(zhí)行,一個可以放在執(zhí)行空間的任務(wù)(實現(xiàn)Runnable接口的中的run(),類似于主線程的main()方法)。線程有“新建”“可執(zhí)行”“執(zhí)行中”三個狀態(tài),而且,一旦線程進(jìn)入了“可執(zhí)行”狀態(tài)后,它會在“可執(zhí)行”和“執(zhí)行中”兩種狀態(tài)中不停地切換(除非處于堵塞狀態(tài))

7, 線程調(diào)度器(the thread scheduler):Java自帶的決定什么時候運行哪個線程的一種機(jī)制,不受用戶的API的控制,所以調(diào)度結(jié)果無法確定(不同的機(jī)器有著不同的執(zhí)行過程,同一臺機(jī)器也會有著不同的執(zhí)行過程)。

8, 可以用sleep()方法來影響調(diào)度器,不過作用效果一般沒有想象中要好。

9, 并發(fā)性問題(concurrency issue):當(dāng)兩個或以上的線程存取單一對象的數(shù)據(jù)的時候,就有機(jī)會發(fā)生各種奇怪的錯誤。為了排除這類問題,使用synchronized(同步化過的)標(biāo)志對象運行中的那些不可分割的過程,類似于一把鎖,鎖住了儲存數(shù)據(jù)的方法,使一個對象對這個數(shù)據(jù)使用完畢之后再允許其他對象使用該數(shù)據(jù)。

第十六章 數(shù)據(jù)結(jié)構(gòu)(集合和泛型)

各種集合(collections)(目前在學(xué)C++版的數(shù)據(jù)結(jié)構(gòu)…討厭的課程)

1, 各種數(shù)據(jù)結(jié)構(gòu):TreeSet(有序防重復(fù)),HashMap(每個數(shù)據(jù)都有對應(yīng)的KEY值),LinkedList(大集合的快速插入和刪除中間元素,這效果,有點像鏈表),HashSet(防重復(fù),可以快速尋找元素),LinkedHashMap(HashMap的升級版,具體看書)。書本的說法是:list對付順序結(jié)構(gòu),set注重獨一無二的性質(zhì),map用key來搜索的專家。

2, 使用System.out.println集合的時候,要覆蓋集合元素的類中的public String toString()方法來設(shè)定輸出的內(nèi)容。

3, 使用Collection.sort(某集合)方法的時候,要求某集合的元素實現(xiàn)排序化(實現(xiàn)Comparable接口之下的public int Compareto()方法),或者用sort的重載方法sort(某集合,某比較器),當(dāng)然之前要現(xiàn)實某比較器(Comparator)中的int Compare()方法。

4, 關(guān)于泛型(generic):java5.0之后推出的功能,為了實現(xiàn)更好的類型安全性。一般用表示,對于集合,也用來表示(E for element),類型參數(shù)會被編譯器自動識別和替換或的位置。然后public void takeThing(ArrayList list)跟public void takeThing(ArrayList list)含義是不一樣的。還有,泛型里面的extends和implements其實都是is的意思,但是創(chuàng)造新的關(guān)鍵字會破壞之前的程序,所以沒有引用is關(guān)鍵字。

5, 對象相等:包括引用相等性和對象相等性,前者指“堆上同一對象的兩個引用”,后者指“堆上的兩個不同對象在意義上是相同的”,一般需要的是后者,要實現(xiàn)后者,就必須覆蓋從Object繼承下來的hashCode()和equals()方法。以HashSet為例,檢查兩個變量是否相等,首先檢查hashCode()的返回是否一樣,然后再檢查equals()函數(shù)的返回是否是true。更加細(xì)節(jié)的東西:hashCode相同并不能保證對象相同的,因為hashCode使用的是雜湊算法。還有就是覆蓋equals()方法是要注意它的參數(shù)是Object類型的。

6, TreeSet的元素必須實現(xiàn)Comparable或者在構(gòu)造的時候用comparator來初始化。

7, 然后是多態(tài)的問題:不知出自什么原因,java設(shè)計時設(shè)定數(shù)組的類型檢查是在運行使其進(jìn)行的,而集合的類型檢查只在編譯時期,所以多態(tài)在集合要實現(xiàn)要麻煩些——public void takeAnimal(ArrayListanimals),注意這里的extends依然和implements一起都是is的意思。

第十七章 發(fā)布程序(包,jar存檔文件和部署)

文件部署,打包成jar什么的,我希望有懶人工具能幫忙打包。

1, 部署分成:完全在本機(jī)的Executable Jar,完全在遠(yuǎn)程的Servlets和介乎兩者之間的JWS(我愛翻譯成“巨猥瑣”)。

2, 源代碼和類文件的分離:源代碼放在source,類文件放在classes,使用命令-d(書上說-d懂的自己建立未建立的目錄,但貌似我這樣做時會提示出錯)

3, 打包JAR:首先,確認(rèn)所有的類文件都在classes目錄下,然后在該目錄下建立manifest.txt來指定哪個類帶有main()方法(Main-Class: **),最后用jar命令打包。(jar –cvmf manifest.txt **.jar *.class)

4, 執(zhí)行JAR:在cmd下用java –jar *.jar命令來啟動,如果自帶GUI,在windows環(huán)境下可以雙擊打開。(若打開是被winrar等程序干擾時,打開方式設(shè)為jre/bin下的javaw.exe,然后在用regedit打開注冊表,在HKEY_CLASSES_ROOT下找到.jar文件的打開方法,在參數(shù)中間添加-jar字樣)

5, 包:主要用于防止類名稱的沖突,關(guān)于制作包執(zhí)行包用包弄JAR等具體命令參看P589左右(懶人表示期待工具)

6, Java web start(JWS):書本介紹較為簡單,還夾雜著XML的語言…

第十八章 分布式計算(遠(yuǎn)程部署的RMI)

終于最后一章了,最后幾章的難度明顯加大呢,可能是因為最后幾章涉及聯(lián)網(wǎng)什么的,那貨其實都可以展開寫一本書了。

1, RMI(remote method invocation):一種連接客戶端和服務(wù)器的技術(shù)(有點像socket)。事實上,在某堆上的對象無法進(jìn)行另外堆上的對象引用,但是利用RMI能夠模擬這種感覺。實現(xiàn)需要四個部分:服務(wù)器(server),客戶端(client),服務(wù)器輔助設(shè)施(server helper),客戶端輔助設(shè)施(client helper)??蛻舳苏{(diào)用客戶端輔助設(shè)施來模擬調(diào)用本機(jī)對象的感覺,而實際上客戶端輔助設(shè)施只是作為代理(proxy),真正實現(xiàn)客戶端請求的是服務(wù)器。

2, RMI調(diào)用方法的過程:客戶端對象對輔助設(shè)置對象調(diào)用方法(已注冊的方法)->客戶端輔助設(shè)施把調(diào)用信息打包通過網(wǎng)絡(luò)送到服務(wù)器的輔助設(shè)施->服務(wù)端的輔助設(shè)施解開來自客戶端輔助設(shè)施的信息,并以此調(diào)用真正的服務(wù)。

3, 創(chuàng)建RMI遠(yuǎn)程服務(wù):步驟一:創(chuàng)建Remote接口(繼承java.rmi.Remote;生命所有的方法都會拋出RemoteException;確定參數(shù)和返回值都是primitive主數(shù)據(jù)類型或者Serializable);步驟二:實現(xiàn)Remote(實現(xiàn)Remote這個接口;繼承UnicastRemoteObject;編寫聲明RemoteExceiption的無參數(shù)構(gòu)造函數(shù);向RMI registry注冊服務(wù));步驟三:用rmic產(chǎn)生stub與skeleton(對實現(xiàn)出的類(不是Remote接口)執(zhí)行rmic);步驟四:啟動RMI registry(調(diào)出命令行來啟動RMI registry);步驟五:啟動遠(yuǎn)程服務(wù)(調(diào)用另一個命令行來啟動服務(wù))

4, Servlet:servlet是完全放在HTTP WEB服務(wù)器上運行的JAVA程序,用于應(yīng)付用戶端沒有JAVA虛擬機(jī)的情況。創(chuàng)建并執(zhí)行servlet的步驟:找出可以存放servlet的地方(就是要買個服務(wù)器);取得servlets.jar并添加到classpath上(上sun官網(wǎng)掛之);通過extend過HttpServlet來編寫servlet的類;編寫HTML來調(diào)用servlet(我不會??);給服務(wù)器設(shè)定HTML的網(wǎng)頁和servlet。

5, JINI(Java Intelligent Network Infrastructure):傳說中一個更加強(qiáng)大的RMI,帶有自適應(yīng)探索(adaptive discovery)和自恢復(fù)網(wǎng)絡(luò)(self-healing networks)。因為很強(qiáng)大,所以書上也沒有篇幅去細(xì)說。后面是實現(xiàn)方法和一堆堆代碼,看得我產(chǎn)生了嚴(yán)重的抵觸情緒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容