第一章 對(duì)象導(dǎo)論
對(duì)象具有狀態(tài)、行為和標(biāo)識(shí)。這意味著每一個(gè)對(duì)象都可以擁有內(nèi)部數(shù)據(jù)和方法,并且每一個(gè)對(duì)象都可以唯一地與其他對(duì)象區(qū)分開(kāi)來(lái)。
每個(gè)對(duì)象都提供服務(wù)
訪問(wèn)控制的第一個(gè)存在原因是讓客戶端程序員無(wú)法觸及他們不應(yīng)該觸及的部分
訪問(wèn)控制的第二個(gè)存在原因是允許庫(kù)設(shè)計(jì)者可以改變類內(nèi)部的工作方式而不用擔(dān)心會(huì)影響到客戶端程序員
包訪問(wèn)權(quán)限:類可以訪問(wèn)在同一個(gè)包(庫(kù)構(gòu)建)中的其他類的成員。但是在包之外,這些成員跟指定private一樣。protected與private區(qū)別在于繼承的類可以訪問(wèn)protected成員,但不能訪問(wèn)private成員
組合:使用現(xiàn)有的類合成新的類(has-a “擁有”關(guān)系)
繼承應(yīng)該只覆蓋類的方法,而不添加在基類中沒(méi)有的新方法嗎?
如果基類與導(dǎo)出類具有完全的接口,稱之為(is-a “是一個(gè)”關(guān)系);
如果導(dǎo)出類中添加了新的接口元素,這種情況下新的類型仍然可以替代基類,但是這種替代并不完美,因?yàn)榛悷o(wú)法訪問(wèn)新添加的方法,稱之為(is-like-a “像是一個(gè)”關(guān)系)
前期綁定:編譯器將產(chǎn)生對(duì)一個(gè)具體的函數(shù)名字的調(diào)用,而運(yùn)行時(shí)將這個(gè)調(diào)用解析到將要被執(zhí)行的代碼的絕對(duì)地址。(非面向?qū)ο缶幊蹋?/p>
后期綁定:當(dāng)向?qū)ο蟀l(fā)送消息時(shí),被調(diào)用的代碼直到運(yùn)行時(shí)才能確定。編譯器確保被調(diào)用方法的存在,并對(duì)調(diào)用參數(shù)和返回值執(zhí)行類型檢查,但是并不知道將被執(zhí)行的確切代碼。
所有的類最終都繼承自單一的基類 -- Object泛型:使用一對(duì)尖括號(hào),中間包含類型信息,通過(guò)這些特征就可以識(shí)別對(duì)泛型的使用。
ArrayListshapes = new ArrayList();
第二章 一切都是對(duì)象
一切都視為對(duì)象,因此可采用單一固定的語(yǔ)法,盡管一切都看作對(duì)象,但操縱的標(biāo)識(shí)符實(shí)際上是對(duì)象的一個(gè)“引用”。用戶可以只創(chuàng)建引用,而不創(chuàng)建對(duì)象與它關(guān)聯(lián)。但是更安全的做法是創(chuàng)建一個(gè)引用的同時(shí)便進(jìn)行初始化。如:String s = "qwer";
存儲(chǔ)數(shù)據(jù)的區(qū)域包括:
(1)寄存器。位于存儲(chǔ)器內(nèi)部,數(shù)量有限,需要根據(jù)需求進(jìn)行分配
(2)堆棧。位于通用RAM(隨機(jī)訪問(wèn)存儲(chǔ)器)中,堆棧指針若向下移動(dòng),則分配新的內(nèi)存;若向上移動(dòng),則釋放這些內(nèi)存。在創(chuàng)建程序時(shí),Java系統(tǒng)必須知道存儲(chǔ)在堆棧內(nèi)的所有項(xiàng)的切確生命周期,以便上下移動(dòng)堆棧指針,因此這個(gè)區(qū)域一般用于存儲(chǔ)對(duì)象引用
(3)堆。一種通用的內(nèi)存池(位于RAM),用于存放所有的Java對(duì)象
(4)常量存儲(chǔ)。通常存放在程序代碼內(nèi)部,它們永遠(yuǎn)不會(huì)被改變
(5)非RAM存儲(chǔ)。如果數(shù)據(jù)完全存活于程序之外,那么它可以不受程序的任何控制,在程序沒(méi)有運(yùn)行時(shí)也可以存在。例如流對(duì)象和持久化對(duì)象
特例:基本類型
不使用new來(lái)創(chuàng)建變量,而是創(chuàng)建一個(gè)并非是引用的“自動(dòng)”變量,這個(gè)變量直接存儲(chǔ)“值”,并置于堆棧中,因此更加高效。
*注意:若**類的某個(gè)成員**是基本數(shù)據(jù)類型,即使沒(méi)有進(jìn)行初始化,Java也會(huì)確保它獲得一個(gè)默認(rèn)值。然而確保初始化的方法并不適用于“局部”變量(即并非某個(gè)類的字段)。
static關(guān)鍵字:當(dāng)聲明一個(gè)事物是static時(shí),就意味著這個(gè)域或者方法不會(huì)與包含它的那個(gè)類的任何對(duì)象實(shí)例關(guān)聯(lián)在一起。所以,即使從未創(chuàng)建某個(gè)類的任何對(duì)象,也可以調(diào)用其static方法或訪問(wèn)其static域。
*靜態(tài)成員和靜態(tài)方法均可以通過(guò)特殊的方式直接調(diào)用:ClassName.i++ 、 ClassName.method();
第三章 操作符
賦值(“ = ”)
基本類型存儲(chǔ)了實(shí)際的數(shù)值,而并非指向一個(gè)對(duì)象的引用,所以在為其賦值的時(shí)候,直接將一個(gè)地方的內(nèi)容復(fù)制到另一個(gè)地方。當(dāng)為對(duì)象“賦值”時(shí),我們真正操作的是對(duì)象的引用,所以倘若“將一個(gè)對(duì)象賦值給另一個(gè)對(duì)象”,實(shí)際是將“引用”從一個(gè)地方復(fù)制到另一個(gè)地方。
自動(dòng)遞增和遞減(++、--)
前綴式:先執(zhí)行運(yùn)算,再生成值
后綴式:先生成值,在執(zhí)行運(yùn)算
關(guān)系操作符
對(duì)象:== 和 != 比較的是對(duì)象的引用,equals()方法被覆蓋時(shí)比較的是對(duì)象的值(否則equals()默認(rèn)比較引用)
基本類型:使用 == 或 != 比較即可
*短路一旦能夠明確無(wú)誤地確定整個(gè)表達(dá)式的值,就不再計(jì)算剩余表達(dá)式的余下部分。因此,整個(gè)邏輯表達(dá)式靠后的部分有可能不會(huì)被運(yùn)算。(利用短路特性,可以獲得性能提升)
指數(shù)計(jì)數(shù)法1.39 x e^-43 在java里實(shí)際表示 1.39 x 10^-43
截尾和舍入
在將float或double轉(zhuǎn)型為整型值時(shí),總是對(duì)該數(shù)字進(jìn)行截尾;如果想得到舍入的結(jié)果,請(qǐng)使用java.lang.Math中的round()方法
第四章 控制執(zhí)行流程
break和continuebreak用于強(qiáng)行退出循環(huán),不執(zhí)行循環(huán)中剩余的語(yǔ)句;continue則停止執(zhí)行當(dāng)前的迭代,然后退回循環(huán)起始處,開(kāi)始下一次迭代。
習(xí)題:吸血鬼數(shù)字如下的為吸血鬼數(shù)字:1260 = 21 * 60;1827 = 21 * 87;2187 = 27 * 81;找出四位數(shù)的所有吸血鬼數(shù)字?
第五章 初始化與清理
1.用構(gòu)造器確保初始化
創(chuàng)建對(duì)象時(shí),如果其類具有構(gòu)造器,Java就會(huì)在用戶有能力操作對(duì)象之前自動(dòng)調(diào)用相應(yīng)的構(gòu)造器,從而保證初始化的進(jìn)行。Java的做法是讓構(gòu)造器采用與類相同的名稱。Java提供了默認(rèn)構(gòu)造器,它是不接受任何參數(shù)的構(gòu)造器
2.方法重載
每個(gè)重載方法都必須有一個(gè)獨(dú)一無(wú)二的參數(shù)類型列表(注意:參數(shù)順序的不同也可以區(qū)分兩個(gè)方法,但不建議這么使用)
注意基本類型的重載
如果傳入的數(shù)據(jù)類型小于方法中聲明的形式參數(shù)類型,實(shí)際數(shù)據(jù)類型就會(huì)被提升。char類型會(huì)被提升為int;如果傳入的實(shí)際參數(shù)較大,就得通過(guò)類型轉(zhuǎn)換來(lái)執(zhí)行窄化轉(zhuǎn)換,否則編譯期會(huì)報(bào)錯(cuò)。
注意:根據(jù)方法的返回值來(lái)區(qū)分重載方法是行不通的。
3.默認(rèn)構(gòu)造器
如果你定義的類里面沒(méi)有構(gòu)造器,則編譯器就會(huì)自動(dòng)幫你創(chuàng)建一個(gè)默認(rèn)構(gòu)造器;如果已經(jīng)定義了一個(gè)構(gòu)造器(無(wú)論是否有參數(shù)),編譯器就不會(huì)幫你自動(dòng)創(chuàng)建默認(rèn)構(gòu)造器。
4.this關(guān)鍵字
只能在方法內(nèi)部使用,表示對(duì)“調(diào)用方法的那個(gè)對(duì)象”的引用。但要注意,如果在方法內(nèi)部調(diào)用同一個(gè)類的另一個(gè)方法,就不必使用this,直接調(diào)用即可。當(dāng)前方法中的this引用會(huì)自動(dòng)應(yīng)用于同一類中的其他方法??赡転橐粋€(gè)類寫(xiě)了多個(gè)構(gòu)造器,有時(shí)可能想在一個(gè)構(gòu)造器中調(diào)用另一個(gè)構(gòu)造器,以避免重復(fù)代碼,可以用this關(guān)鍵字做到這一點(diǎn)。
static的含義:在static方法的內(nèi)部不能夠調(diào)用非靜態(tài)方法,反過(guò)來(lái)倒是可以的。而且可以在沒(méi)有創(chuàng)建任何對(duì)象的前提下,僅僅通過(guò)類本身來(lái)調(diào)用static方法。Java中禁止使用全局方法,但你在類中置入static方法就可以訪問(wèn)其他static方法和static域。
5.清理:終結(jié)處理和垃圾回收
finalize()方法
①對(duì)象可能不被垃圾回收
②垃圾回收不等于“析構(gòu)”
③垃圾回收只與內(nèi)存有關(guān)
構(gòu)造器初始化
①初始化順序
在類的內(nèi)部,變量定義的先后順序決定了初始化的順序。即使變量定義散布于方法定義之間,它們?nèi)耘f會(huì)在任何方法(包括構(gòu)造器)被調(diào)用之前得到初始化。
②靜態(tài)數(shù)據(jù)的初始化
無(wú)論創(chuàng)建多少個(gè)對(duì)象,靜態(tài)數(shù)據(jù)都只占用一份存儲(chǔ)區(qū)域。初始化的順序是先靜態(tài)對(duì)象,而后是“非靜態(tài)”對(duì)象
總結(jié)一下對(duì)象的構(gòu)建過(guò)程(以一個(gè)名為Dog的類為例):
a.即使沒(méi)有顯式的使用static關(guān)鍵字,構(gòu)造器實(shí)際上也是靜態(tài)方法。因此,當(dāng)首次創(chuàng)建類型為Dog的對(duì)象時(shí),或者Dog類的靜態(tài)方法/靜態(tài)域首次被訪問(wèn)時(shí),Java解釋器必須查找類路徑,以定位Dog.class文件。
b.然后載入Dog.class,有關(guān)靜態(tài)初始化的所有動(dòng)作都會(huì)執(zhí)行。因此,靜態(tài)初始化只在Class對(duì)象首次加載的時(shí)候進(jìn)行一次。
c.當(dāng)用new Dog()創(chuàng)建對(duì)象的時(shí)候,首先在堆上為Dog對(duì)象分配足夠的存儲(chǔ)空間。
d.這塊存儲(chǔ)空間會(huì)被清零,這就自動(dòng)的將Dog對(duì)象中的所有基本類型數(shù)據(jù)都設(shè)置成了默認(rèn)值,而引用被設(shè)置成了null。
e.執(zhí)行所有出現(xiàn)于字段定義處的初始化動(dòng)作。
f.執(zhí)行構(gòu)造器。
6.枚舉類型
關(guān)鍵字enum,簡(jiǎn)單例子如下:
public enum Spiciness{NOT,MILD,MEDIUM,HOT,FLAMING}
第六章 訪問(wèn)權(quán)限控制
訪問(wèn)控制權(quán)限的等級(jí),從最大權(quán)限到自小權(quán)限依次為:public、protected、包訪問(wèn)權(quán)限、private
*包訪問(wèn)權(quán)限
意味著當(dāng)前包中的所有其他類對(duì)那個(gè)成員都有訪問(wèn)權(quán)限,但對(duì)于這個(gè)包之外的所有類,這個(gè)成員都是private。取得對(duì)某成員的訪問(wèn)權(quán)的唯一途徑是:
①使該成員成為public
②通過(guò)不加訪問(wèn)權(quán)限修飾詞并將其他類放置于同一個(gè)包內(nèi)方式給成員賦予包訪問(wèn)權(quán)
③繼承而來(lái)的類即可以訪問(wèn)public成員也可以訪問(wèn)protected成員,但是不能訪問(wèn)private
④提供訪問(wèn)器和變異器方法(也稱get/set方法),以讀取和改變數(shù)值
默認(rèn)包
當(dāng)兩個(gè)Java文件處于相同的目錄并且沒(méi)有給自己設(shè)定任何包名稱時(shí),Java默認(rèn)將它們看做隸屬于該目錄的默認(rèn)包之中,于是他們?yōu)樵撃夸浿械乃衅渌募继峁┝税L問(wèn)權(quán)限。
接口和實(shí)現(xiàn)
訪問(wèn)權(quán)限控制將權(quán)限的邊界毀在了數(shù)據(jù)類型的內(nèi)部:
第一個(gè)原因是要設(shè)定客戶端程序員可以使用和不可以使用的界限。
第二個(gè)原因即將接口和具體實(shí)現(xiàn)進(jìn)行分離。
第七章 復(fù)用類
組合:在新的類中產(chǎn)生現(xiàn)有類的對(duì)象。
繼承:按照現(xiàn)有類的類型來(lái)創(chuàng)建新類,無(wú)需改變現(xiàn)有類的形式,采用現(xiàn)有類的形式并在其中添加新代碼。
*注意:toString(),每一個(gè)非基本類型的對(duì)象都有一個(gè)toString()方法,而且當(dāng)編譯器需要一個(gè)String而你卻只有一個(gè)對(duì)象時(shí),該方法就會(huì)被調(diào)用。
編譯器并不是簡(jiǎn)單的為每一個(gè)引用都創(chuàng)建默認(rèn)對(duì)象,如果想初始化這些引用,可以再代碼中的下列位置進(jìn)行:
①在定義對(duì)象的地方。這意味著他們總是能夠在構(gòu)造器被調(diào)用之前被初始化
②在類的構(gòu)造器中
③就在正要使用這些對(duì)象之前,這種方式成為惰性初始化
④使用實(shí)例初始化
初始化基類
在構(gòu)造器中調(diào)用基類構(gòu)造器來(lái)執(zhí)行初始化,而基類構(gòu)造器具有執(zhí)行基類初始化所需要的所有內(nèi)容。Java會(huì)自動(dòng)在導(dǎo)出類的構(gòu)造器中插入對(duì)基類構(gòu)造器的調(diào)用。當(dāng)存在繼承關(guān)系時(shí),構(gòu)建過(guò)程是從基類“向外”擴(kuò)散的,所以基類在導(dǎo)出類構(gòu)造器可以訪問(wèn)它之前,已經(jīng)完成了初始化。
*帶參數(shù)的構(gòu)造器
如果沒(méi)有默認(rèn)的基類構(gòu)造器,或者想調(diào)用一個(gè)帶參數(shù)的基類構(gòu)造器,就必須用關(guān)鍵字super顯式的編寫(xiě)調(diào)用基類構(gòu)造器的語(yǔ)句。
代理
繼承和組合之間的中庸之道,因?yàn)槲覀儗⒁粋€(gè)成員對(duì)象置于所要構(gòu)造的類中(就像組合),但此時(shí)我們?cè)谛骂愔杏直┞读嗽摮蓡T對(duì)象的所有方法(就像繼承)。
在組合和繼承之間做出選擇
組合技術(shù)通常用于想在新類中使用現(xiàn)有類的功能而非它的接口這種情形。即在新類中嵌入某個(gè)對(duì)象,讓其實(shí)現(xiàn)所需要的功能,但新類的用戶看到的只是為新類所定義的接口,而非所嵌入對(duì)象的接口。為取得此效果,需要在新類中嵌入一個(gè)現(xiàn)有類的private對(duì)象。
protected關(guān)鍵字
指明“就類用戶而言,這是private的,但對(duì)于任何繼承于此類的導(dǎo)出類或其他任何位于同一個(gè)包內(nèi)的類來(lái)說(shuō),它卻是可以訪問(wèn)的(提供了包訪問(wèn)權(quán)限)”
*向上轉(zhuǎn)型
由導(dǎo)出類轉(zhuǎn)型成基類,在繼承圖上是向上移動(dòng)的,因此一般稱為向上轉(zhuǎn)型。由于向上轉(zhuǎn)型是從一個(gè)較為專業(yè)的類型向較為通用的類型轉(zhuǎn)換的,所以總是很安全的。
final關(guān)鍵字
可能使用到final的三種情況:
①final數(shù)據(jù)
一個(gè)永不改變的編譯時(shí)常量一個(gè)在運(yùn)行時(shí)被初始化的值,而你不希望它被改變當(dāng)final用于對(duì)象引用時(shí),表示引用恒定不變,一旦引用被初始化指向一個(gè)對(duì)象,就無(wú)法再把它改為指向另一個(gè)對(duì)象
創(chuàng)建一個(gè)含有static final域和final域的類,說(shuō)明二者間的區(qū)別?
②final方法
第一個(gè)原因是把方法鎖定,以防止任何繼承類修改它的含義
第二個(gè)原因是效率
③final類
表明不打算繼承該類,該類的設(shè)計(jì)永不需要做任何變動(dòng),該類沒(méi)有任何子類。
初始化及類的加載
類的代碼在初次使用時(shí)才加載,通常是指加載發(fā)生于創(chuàng)建類的第一個(gè)對(duì)象之時(shí),但是當(dāng)訪問(wèn)static域或static方法時(shí),也會(huì)發(fā)生加載。
第八章 多態(tài)
方法調(diào)用綁定將一個(gè)方法調(diào)用同一個(gè)方法主體關(guān)聯(lián)起來(lái)被稱作綁定。若在程序執(zhí)行前進(jìn)行綁定,叫做前期綁定。
后期綁定:在運(yùn)行時(shí)根據(jù)對(duì)象的類型進(jìn)行綁定,也稱為動(dòng)態(tài)綁定或運(yùn)行時(shí)綁定。
注意:Java中除了static方法和final方法(private方法屬于final方法)之外,其他所有的方法都是后期綁定。
只有非private方法才可以被覆蓋,因?yàn)閜rivate方法被默認(rèn)為是final方法且對(duì)導(dǎo)出類是屏蔽的。在導(dǎo)出類中如果想覆蓋基類中的private方法,最好采用不同的名字。
注意:如果你直接訪問(wèn)域,這個(gè)訪問(wèn)就將在編譯期進(jìn)行解析。如果某個(gè)方法是靜態(tài)的,它的行為就不具有多態(tài)性。
對(duì)象調(diào)用構(gòu)造器需要遵照下面的順序:
①調(diào)用基類構(gòu)造器。(這個(gè)步驟會(huì)不斷地反復(fù)遞歸下去)
②按聲明順序調(diào)用成員的初始化方法
③調(diào)用導(dǎo)出類構(gòu)造器的主體
*初始化的實(shí)際過(guò)程
①在其他任何事物發(fā)生之前,將分配給對(duì)象的存儲(chǔ)空間初始化成二進(jìn)制的零
②如之前描述那樣調(diào)用基類構(gòu)造器
③按照聲明的順序調(diào)用成員的初始化方法
④調(diào)用導(dǎo)出類的構(gòu)造器主體
一條通用的準(zhǔn)則:用繼承表達(dá)行為間的差異,并用字段表達(dá)狀態(tài)上的變化。
第九章 接口
1、抽象類和抽象方法
抽象方法:僅有聲明而沒(méi)有方法體。語(yǔ)法是 abstract void f();
抽象類:包含抽象方法的類
2、接口
關(guān)鍵字:interface
產(chǎn)生一個(gè)完全抽象的類,它根本就沒(méi)有提供任何具體實(shí)現(xiàn),它允許創(chuàng)建者確定方法名、參數(shù)列表和返回類型,但是沒(méi)有任何的方法體。接口中可以包含域,但是這些域隱式地是static和final的。
3、完全解耦
策略模式:創(chuàng)建一個(gè)能夠根據(jù)所傳遞的參數(shù)對(duì)象的不同而具有不同行為的方法。
適配器模式:接受擁有的接口,并產(chǎn)生需要的接口。
4、Java中的多重繼承
在C++中組合多個(gè)類的接口行為被稱為多重繼承,但是由于每個(gè)類有一個(gè)具體實(shí)現(xiàn),因此比較繁雜;在Java中,可以通過(guò)組合多個(gè)接口而只有一個(gè)類有具體實(shí)現(xiàn)的方式來(lái)避免這個(gè)問(wèn)題。
5、通過(guò)繼承來(lái)擴(kuò)展接口
通過(guò)繼承,可以很容易地在接口中添加新的方法聲明,還可以通過(guò)繼承在新接口中組合數(shù)個(gè)接口,這兩種情況都可以獲得新的接口。
*一般情況下,只可以將extends用于單一類,但是可以引用多個(gè)基類接口。
6、適配接口
接口最吸引人的地方就是允許同一個(gè)接口具有多個(gè)不同的具體實(shí)現(xiàn)。在簡(jiǎn)單情況下,它的體現(xiàn)形式通常是一個(gè)接受接口類型的方法,而該接口的實(shí)現(xiàn)和向該方法傳遞的對(duì)象則取決于方法的使用者。
7、接口中的域
因?yàn)榻涌谥械娜魏斡蚨甲詣?dòng)是static和final的,所以接口成為了一種很便捷的用來(lái)創(chuàng)建常量組的工具。
初始化接口中的域:在接口中定義的域不能是“空f(shuō)inal”,但是可以被非常量表達(dá)式初始化。既然域是static的,它們就可以在類第一次被加載時(shí)初始化,這發(fā)生在任何域首次比訪問(wèn)時(shí)。
8、嵌套接口
接口可以嵌套在類或其他接口中。
第十章 內(nèi)部類
1、創(chuàng)建內(nèi)部類
內(nèi)部類:可以將一個(gè)類的定義放在另一個(gè)類的定義內(nèi)部。如果想從外部類的非靜態(tài)方法之外的任何位置創(chuàng)建某個(gè)內(nèi)部類的對(duì)象,那么必須像在main()方法中那樣,具體地指明這個(gè)對(duì)象的類型:OuterClassName.InnerClassName
2、鏈接到外部類
當(dāng)生成一個(gè)內(nèi)部類的對(duì)象時(shí),此對(duì)象與制造它的外圍對(duì)象之間就有了一種聯(lián)系,所以它能訪問(wèn)其外圍對(duì)象的所有成員,而不需要任何特殊條件。此外,內(nèi)部類還擁有其外圍類的所有元素的訪問(wèn)權(quán)。
3.使用.this與.new
如果你需要生成對(duì)外部類對(duì)象的引用,可以使用外部類的名字后面緊跟.this。這樣產(chǎn)生的引用自動(dòng)地具有正確的類型,這一點(diǎn)在編譯期就被知曉并受到檢查,因?yàn)闆](méi)有任何運(yùn)行時(shí)開(kāi)銷。如果你想要告知某些其他對(duì)象,去創(chuàng)建某個(gè)內(nèi)部類的對(duì)象,就需要使用.new語(yǔ)法來(lái)提供對(duì)外部類對(duì)象的引用。
*要想直接創(chuàng)建內(nèi)部類的對(duì)象,不能直接去引用外部類的名字,而是必須使用外部類的對(duì)象來(lái)創(chuàng)建該內(nèi)部類對(duì)象。
4.內(nèi)部類與向上轉(zhuǎn)型
當(dāng)將內(nèi)部類向上轉(zhuǎn)型為其基類,尤其是轉(zhuǎn)型為一個(gè)接口的時(shí)候,內(nèi)部類就有了用武之地。因?yàn)閮?nèi)部類(某個(gè)接口的實(shí)現(xiàn))能夠完全不可見(jiàn)、并且不可用。所得到的只是指向基類或接口的引用,能夠很方便地隱藏細(xì)節(jié)。
5.在方法和作用域內(nèi)的類
也稱之為局部?jī)?nèi)部類。這么做有兩個(gè)理由:
①你實(shí)現(xiàn)了某類型的接口,于是可以創(chuàng)建并返回其引用。
②你要解決一個(gè)復(fù)雜的問(wèn)題,想創(chuàng)建一個(gè)類來(lái)輔助你的解決方案,但是又不希望這個(gè)類是公共可用的。
6.匿名內(nèi)部類
在匿名內(nèi)部類中不能有命名構(gòu)造器,但通過(guò)實(shí)力初始化,就能夠達(dá)到為匿名內(nèi)部類創(chuàng)建一個(gè)構(gòu)造器的效果。
7.嵌套類
如果不需要內(nèi)部類對(duì)象與其外圍類對(duì)象之間有聯(lián)系,那么可以將內(nèi)部類聲明為static,這通常稱之為嵌套類。嵌套類意味著:
①要?jiǎng)?chuàng)建嵌套類的對(duì)象,并不需要其外圍類的對(duì)象
②不能從嵌套類的對(duì)象中訪問(wèn)非靜態(tài)的外圍類對(duì)象
8.為什么需要內(nèi)部類
使用內(nèi)部類最吸引人的原因是:每個(gè)內(nèi)部類都能獨(dú)立地繼承自一個(gè)接口的實(shí)現(xiàn),所以無(wú)論外圍類是否已經(jīng)繼承了某個(gè)接口的實(shí)現(xiàn),對(duì)于內(nèi)部類都沒(méi)有影響。
內(nèi)部類的其他特性:
①內(nèi)部類可以有多個(gè)實(shí)例,每個(gè)實(shí)例都有自己的狀態(tài)信息,并且與其外圍類對(duì)象的信息相互獨(dú)立。
②在單個(gè)外圍類中,可以讓多個(gè)內(nèi)部類以不同的方式實(shí)現(xiàn)同一個(gè)接口或者繼承同一個(gè)類。
③創(chuàng)建內(nèi)部類對(duì)象的時(shí)刻并不依賴于外圍類對(duì)象的創(chuàng)建。
④內(nèi)部類并沒(méi)有令人迷惑的“is-a”關(guān)系,它就是一個(gè)獨(dú)立的實(shí)體。
9.內(nèi)部類的繼承
因?yàn)閮?nèi)部類的構(gòu)造器必須連接到指向其外圍類對(duì)象的引用,所以在繼承內(nèi)部類時(shí),那個(gè)指向外圍類對(duì)象的“秘密的”引用必須被初始化,而在導(dǎo)出類中不再存在可連接的默認(rèn)對(duì)象。特殊語(yǔ)法:enclosingClassReference.super();
10.內(nèi)部類可以被覆蓋嗎?
當(dāng)繼承了某個(gè)外圍類的時(shí)候,內(nèi)部類并沒(méi)有發(fā)生什么特別神奇的變化。這兩個(gè)內(nèi)部類是完全獨(dú)立的兩個(gè)實(shí)體,各自在自己的命名空間內(nèi)。當(dāng)然,明確地繼承某個(gè)內(nèi)部類是可以的,這么做可以覆蓋舊類的方法。
11.局部?jī)?nèi)部類
可以在代碼塊里創(chuàng)建內(nèi)部類,典型的方式是在一個(gè)方法體的里面創(chuàng)建。局部?jī)?nèi)部類不能有訪問(wèn)說(shuō)明符,因?yàn)樗皇峭鈬惖囊徊糠?,但是它可以訪問(wèn)當(dāng)前代碼塊內(nèi)的常量,以及此外圍類所有成員。
為什么使用局比內(nèi)部類而不是匿名內(nèi)部類?
理由一是我們需要一個(gè)已命名的構(gòu)造器或者需要重載構(gòu)造器,而匿名內(nèi)部類只能用于實(shí)例初始化。另一個(gè)理由是需要不止一個(gè)該內(nèi)部類的對(duì)象。
12.內(nèi)部類標(biāo)識(shí)符
內(nèi)部類文件的命名有嚴(yán)格的規(guī)則:外圍類的名字 + “$” + 內(nèi)部類的名字(LocalInnerClass$LocalCounter.class)
第11章 持有對(duì)象
1.泛型和類型安全的容器
通過(guò)指定容器實(shí)例可以保存的類型,可以在編譯期防止將錯(cuò)誤類型的對(duì)象放置到容器中。語(yǔ)法是:ArrayList
當(dāng)你指定了某個(gè)類型作為泛型參數(shù)時(shí),并不限于只能將該確切類型的對(duì)象放置到容器中,向上轉(zhuǎn)型也可以像作用于其他類型一樣作用于泛型。
2.基本概念
Java容器類庫(kù)的作用是“保存對(duì)象”,可以劃分為兩大類:
①Collection
一個(gè)獨(dú)立元素的序列,這些元素都服從一條或多條規(guī)則。
②Map
一組成對(duì)的“鍵值對(duì)”對(duì)象,允許你使用鍵來(lái)查找值。
3.List
有兩種類型的List:
①ArrayList
長(zhǎng)于隨機(jī)訪問(wèn)元素,但是在List的中間插入和移除元素較慢
②LinkedList
進(jìn)行插入和刪除操作較快,但是在隨機(jī)訪問(wèn)方面相對(duì)較慢。它的特性集較ArrayList更大
4.迭代器
迭代器是一個(gè)對(duì)象,它的工作是遍歷并選擇序列中的對(duì)象,而客戶端程序員不必知道或關(guān)心該序列底層的結(jié)構(gòu)。
Java中的Iterator對(duì)象只能單向移動(dòng),并且只能用來(lái):
①使用方法iterator()要求容器返回一個(gè)Iterator。Iterator將準(zhǔn)備好返回序列的第一個(gè)元素
②使用next()獲得序列中的下一個(gè)元素
③使用hasNext()檢查序列中是否還有元素
④使用remove()將迭代器新近返回的元素刪除
第12章 通過(guò)異常處理錯(cuò)誤
概念
用強(qiáng)制規(guī)定的形式來(lái)消除錯(cuò)誤處理過(guò)程中隨心所欲的因素。
基本異常
異常情形是指阻止當(dāng)前方法或作用域繼續(xù)執(zhí)行的問(wèn)題。對(duì)于異常情形,因?yàn)楫?dāng)前環(huán)境下無(wú)法獲得必要的信息來(lái)解決問(wèn)題,所以要從當(dāng)前環(huán)境跳出,并且把問(wèn)題提交給上一級(jí)環(huán)境。
捕獲異常
try塊:嘗試各種可能產(chǎn)生異常的方法調(diào)用。
異常處理程序:通常緊跟在try塊之后,以關(guān)鍵字catch表示。
創(chuàng)建自定義異常
必須從已有的異常類繼承,最好選擇意思相近的異常類繼承。建立新的異常類型最簡(jiǎn)單的方法是讓編譯器為你產(chǎn)生默認(rèn)構(gòu)造器。
異常說(shuō)明
使用附加的關(guān)鍵字throws,后面接一個(gè)所有潛在異常類型的列表
Java標(biāo)準(zhǔn)異常
Throwable類被用來(lái)表示任何可以作為一場(chǎng)被拋出的類。它又可以分為兩大類:
①Error
用來(lái)表示編譯時(shí)和系統(tǒng)錯(cuò)誤
②Exception
可以被拋出的基本類型,在Java類庫(kù)、用戶方法以及運(yùn)行時(shí)故障都可能拋出Exception異常
使用finally進(jìn)行清理
對(duì)于一些代碼,可能會(huì)希望無(wú)論try塊中的異常是否拋出,它們都能得到執(zhí)行。這種情況下,就要使用finally子句是否被拋出,finally子句總是執(zhí)行
*在return中使用finally:因?yàn)閒inally子句總是會(huì)執(zhí)行,所以在一個(gè)方法中,可以從多個(gè)點(diǎn)返回,并且可以保證重要的清理工作依然會(huì)執(zhí)行
缺憾:異常丟失
異常作為程序出錯(cuò)的標(biāo)志,決不應(yīng)該被忽略,但它還是有可能被忽略,用某些特殊的方式使用finally子句,就會(huì)發(fā)生這種情況。(在finally中拋出新的異常覆蓋原先拋出的異常)
異常匹配
拋出異常的時(shí)候,異常處理系統(tǒng)會(huì)按照代碼的書(shū)寫(xiě)順序找出“最近”的處理程序。找到匹配的處理程序之后,它就不會(huì)再繼續(xù)查找。
注意:查找的時(shí)候并不要求拋出的異常同處理程序所聲明的異常完全匹配,派生類的對(duì)象也可以匹配其基類的處理程序。如果把捕獲基類的catch子句放在最前面,以此想把派生類的異常給“屏蔽”掉,這樣編譯器就會(huì)報(bào)告錯(cuò)誤。
異常使用指南:
①在知道該如何處理的情況下捕獲異常
②解決問(wèn)題并且重新調(diào)用產(chǎn)生異常的方法
③進(jìn)行少許修補(bǔ),然后繞過(guò)異常發(fā)生的地方繼續(xù)執(zhí)行
④用別的數(shù)據(jù)進(jìn)行計(jì)算,以代替方法預(yù)計(jì)會(huì)返回的值
⑤把當(dāng)前運(yùn)行環(huán)境下能做的事情盡量做完,然后把相同的異常重拋到更高層
⑥把當(dāng)前運(yùn)行環(huán)境下能做的事情盡量做完,然后把不同的異常重拋到更高層
⑦終止程序
⑧進(jìn)行簡(jiǎn)化
⑨讓類庫(kù)和程序更安全
第13章 字符串
1.不可變String
String對(duì)象是不可變的。String類中每一個(gè)看起來(lái)會(huì)修改String值的方法,實(shí)際上都是創(chuàng)建一個(gè)全新的String對(duì)象,以包含修改后的字符串內(nèi)容。而最初的String對(duì)象紋絲不動(dòng)。
2.重載“+”與StringBuilder
一個(gè)操作符在應(yīng)用于特定的類時(shí),被賦予了特殊的意義。操作符“+”可以用來(lái)連接String。使用StringBuilder不會(huì)生成多個(gè)String對(duì)象,并且提供了豐富而全面的方法,包括insert()、replace()。。。
3.格式化輸出
①printf()
printf("Row 1: [%d %f]\n", x, y);%d和%f稱為格式修飾符,它們不但說(shuō)明插入數(shù)據(jù)的位置,同時(shí)還說(shuō)明了將插入什么類型的變量。此處%d表示x是一個(gè)整數(shù),%f表示y是一個(gè)浮點(diǎn)數(shù)
②System.out.format()
與printf()方法等價(jià)
③Formatter類
可以看成一個(gè)翻譯器,它將你的格式化字符串與數(shù)據(jù)翻譯成需要的結(jié)果,當(dāng)你創(chuàng)建一個(gè)Fomatter對(duì)象的時(shí)候,需要向其構(gòu)造器傳遞一些信息,告訴它最終的結(jié)果將向哪里輸出。
4.正則表達(dá)式
String類自帶了一個(gè)非常有用的正則表達(dá)式工具--split()方法,其功能是“將字符串從正則表達(dá)式匹配的地方切開(kāi)”String類自帶的另一個(gè)正則表達(dá)式工具是“替換”,你可以只替換正則表達(dá)式第一個(gè)匹配的子串(replaceFirst)或是替換所有匹配的地方(replaceAll)
第14章 類型信息
Java是如何讓我們?cè)谶\(yùn)行時(shí)識(shí)別對(duì)象和類的信息的?
主要的方式有兩種:
①“傳統(tǒng)的”RTTI,它假定我們?cè)诰幾g時(shí)已經(jīng)知道了所有的類型
②“反射”機(jī)制,它允許我們?cè)谶\(yùn)行時(shí)發(fā)現(xiàn)和使用類的信息
1.為什么需要RTTI
在Java中,所有的類型轉(zhuǎn)換都是在運(yùn)行時(shí)進(jìn)行正確性檢查的。這也是RTTI名字的含義:在運(yùn)行時(shí),識(shí)別一個(gè)對(duì)象的類型。
2.Class對(duì)象
類型信息在運(yùn)行時(shí)是如何表示的?
這項(xiàng)工作是由稱為Class對(duì)象的特殊對(duì)象完成的,它包含了與類相關(guān)的信息。每當(dāng)編寫(xiě)并且編譯一個(gè)新類,就會(huì)產(chǎn)生一個(gè)Class對(duì)象。為了生成這個(gè)類的對(duì)象,運(yùn)行這個(gè)程序的Java虛擬機(jī)將使用被稱為“類加載器”的子系統(tǒng)。
所有的類都是在對(duì)其第一次使用時(shí),動(dòng)態(tài)加載到JVM中的,當(dāng)程序創(chuàng)建第一個(gè)對(duì)類的靜態(tài)成員的引用時(shí),就會(huì)加載這個(gè)類。這個(gè)證明構(gòu)造器也是類的靜態(tài)方法,即使構(gòu)造器沒(méi)有使用static關(guān)鍵字。因此,使用new操作符創(chuàng)建類的新對(duì)象也會(huì)被當(dāng)做類的靜態(tài)成員的引用。因此,Java程序在它開(kāi)始運(yùn)行之前并非被完全加載,其各個(gè)部分是在必需時(shí)才加載的。類加載器首先檢查這個(gè)類的Class對(duì)象是否已經(jīng)加載。如果沒(méi)有加載,默認(rèn)的類加載器就會(huì)根據(jù)類名查找.class文件,在這個(gè)類的字節(jié)碼被加載時(shí),它們會(huì)接受驗(yàn)證,保證其沒(méi)有被破壞,并沒(méi)有包含不良Java代碼。一旦某個(gè)類的Class對(duì)象被載入內(nèi)存,它就會(huì)用來(lái)創(chuàng)建這個(gè)類的所有對(duì)象。
getName()產(chǎn)生全限定的類名,getSimpleName()產(chǎn)生不含包名的類名,getCanonicalName()產(chǎn)生全限定的類名。getInterface方法返回一個(gè)Class對(duì)象,它表示Class對(duì)象中所包含的接口;getSuperclass方法查詢其直接基類。
*類字面常量
如:FancyToy.class類字面常量不僅可以用于普通的類,也可應(yīng)用于接口、數(shù)組以及基本數(shù)據(jù)類型。另外,用于基本類型的包裝器類,還有一個(gè)標(biāo)準(zhǔn)字段TYPE。如Character.TYPE等價(jià)于char.class
*注意:有一點(diǎn)非常有趣,當(dāng)使用“.class”來(lái)創(chuàng)建對(duì)Class對(duì)象的引用時(shí),不會(huì)自動(dòng)地初始化該Class對(duì)象。為了使用類而做的準(zhǔn)備工作實(shí)際包含三個(gè)步驟:
①加載,這是由類加載器執(zhí)行的,該步驟將查找字節(jié)碼,并從這些字節(jié)碼中創(chuàng)建一個(gè)Class對(duì)象;
②鏈接,在鏈接階段將驗(yàn)證類中的字節(jié)碼,為靜態(tài)域分配存儲(chǔ)空間,并且如果必需的話,將解析這個(gè)類創(chuàng)建的對(duì)其他類的所有引用;
③初始化,如果該類具有超類,則對(duì)其初始化,執(zhí)行靜態(tài)初始化器和靜態(tài)初始化塊。新的轉(zhuǎn)型語(yǔ)法:cast()cast()方法接受參數(shù)對(duì)象,并將其轉(zhuǎn)型為Class引用的類型
3.類型轉(zhuǎn)換前先做檢查
RTTI在Java中的第三種形式:關(guān)鍵字instanceof它返回一個(gè)布爾值,告訴我們對(duì)象是不是某個(gè)特定類型的實(shí)例。使用方法:if(x instanceof Dog)對(duì)instanceof有嚴(yán)格的限制:只可將其與命名類型進(jìn)行比較,而不能與Class對(duì)象作比較。
動(dòng)態(tài)的instanceof:Class.isInstance方法提供了一種動(dòng)態(tài)地測(cè)試對(duì)象的途徑。
4.instanceof和Class的等價(jià)性
在查詢類型信息時(shí),以instanceof的形式(包含instanceof和isInstance)與直接比較Class對(duì)象有一個(gè)重要的差別instanceof保持了類型的概念(比較類和它的派生類),而如果用==比較實(shí)際的Class對(duì)象,就沒(méi)有考慮繼承。
5.反射:運(yùn)行時(shí)的類信息
在編譯時(shí),編譯器必須知道所有要通過(guò)RTTI來(lái)處理的類。Class類與java.lang.reflect類庫(kù)一起對(duì)反射的概念進(jìn)行了支持,該類庫(kù)包含了Field、Merhod以及Constructor類這些類型的對(duì)象是由JVM在運(yùn)行時(shí)創(chuàng)建的,用以表示未知類里對(duì)應(yīng)的成員。
RTTI和反射之間真正的區(qū)別在于:對(duì)RTTI來(lái)說(shuō),編譯器在編譯時(shí)打開(kāi)和檢查.class文件;而對(duì)于反射來(lái)說(shuō),.class文件在編譯時(shí)是不可獲取的,所以在運(yùn)行時(shí)打開(kāi)和檢查.class文件。
Class的getMethods()和getConstructors()方法分別返回Methods對(duì)象的數(shù)組和Constructor對(duì)象的數(shù)組。這兩個(gè)類都提供了深層方法,用以解析其對(duì)象所代表的方法,并獲取其名字、輸入?yún)?shù)以及返回值。
6.動(dòng)態(tài)代理
代理是基本的設(shè)計(jì)模式之一,它是你為了提供額外的或不同的操作,而插入的用來(lái)代替“實(shí)際”對(duì)象的對(duì)象。這些操作通常涉及與“實(shí)際”對(duì)象的通信,因此代理通常充當(dāng)著中間人的角色。Java的動(dòng)態(tài)代理比代理的思想更向前邁進(jìn)一步,因?yàn)樗梢詣?dòng)態(tài)地創(chuàng)建代理并動(dòng)態(tài)地處理對(duì)所代理方法的調(diào)用。在動(dòng)態(tài)代理上所做的所有調(diào)用都會(huì)被重定向到單一的調(diào)用處理器上,它的工作是揭示調(diào)用的類型并確定相應(yīng)的對(duì)策
7.null對(duì)象
當(dāng)你使用內(nèi)置的null表示缺少對(duì)象時(shí),在每次使用引用時(shí)都必須測(cè)試其是否為null。這顯得很枯燥。空對(duì)象最有用之處在于它更靠近數(shù)據(jù),因?yàn)閷?duì)象表示的是問(wèn)題空間內(nèi)的實(shí)體。
8.接口與類型信息
inteface關(guān)鍵字的一種重要目標(biāo)就是允許程序員隔離構(gòu)件,進(jìn)而降低耦合性。
第15章 泛型
泛型實(shí)現(xiàn)了參數(shù)化類型的概念,使代碼可以應(yīng)用于多種類型。
1.簡(jiǎn)單泛型
Java泛型的核心概念:告訴編譯器想使用什么類型,然后編譯器幫你處理一切細(xì)節(jié)。
2.泛型方法
目前,我們見(jiàn)到的泛型都是用于整個(gè)類上的,但同樣可以在類中包含參數(shù)化方法,并且這個(gè)方法所在的類可以是泛型類,也可以不是泛型類。要定義泛型方法,只需將泛型參數(shù)列表置于返回值之前,如:publicvoid f(x){ };
3.問(wèn)題
①任何基本類型都不能作為類型參數(shù)
②實(shí)現(xiàn)參數(shù)化接口:一個(gè)類不能實(shí)現(xiàn)同一個(gè)泛型接口的兩種變體,由于擦除的原因,這兩個(gè)變體會(huì)成為相同的接口
③轉(zhuǎn)型和警告
④重載
⑤基類劫持了接口
第16章 數(shù)組
1.數(shù)組為什么特殊
數(shù)組與其他種類的容器之間的區(qū)別有三點(diǎn):
①效率:在Java中,數(shù)組是一種效率最高的存儲(chǔ)和隨機(jī)訪問(wèn)對(duì)象引用序列的方式
②類型:數(shù)組是一個(gè)簡(jiǎn)單的線性序列,使得元素訪問(wèn)非??焖?/p>
③保存基本類型的能力:數(shù)組對(duì)象的大小被固定,并且在其生命周期中不可改變
2.數(shù)組是第一級(jí)對(duì)象
對(duì)象數(shù)組和基本類型數(shù)組在使用上幾乎是相同的,唯一的區(qū)別就是對(duì)象數(shù)組保存的是引用,基本類型數(shù)組直接保存
基本類型的值。
3.返回一個(gè)數(shù)組
在Java中,可以直接“返回一個(gè)數(shù)組”,而無(wú)需擔(dān)心要為數(shù)組負(fù)責(zé) -- 只要你需要它,它就會(huì)一直存在,當(dāng)你使用
完后,垃圾回收器會(huì)清理掉它。
4.多維數(shù)組
創(chuàng)建多維數(shù)組很方便。對(duì)于基本類型的多維數(shù)組,可以通過(guò)使用花括號(hào)將每個(gè)向量分隔開(kāi)。
5.數(shù)組與泛型
通常,數(shù)組與泛型不能很好地結(jié)合。你不能實(shí)例化具有參數(shù)化類型的數(shù)組,擦除會(huì)移除參數(shù)類型信息,而數(shù)組必須
知道它們所持有的確切類型,以強(qiáng)制保證類型安全。但是,你可以參數(shù)化數(shù)組本身的類型。
6.Arrays實(shí)用功能
①?gòu)?fù)制數(shù)組
System.arraycopy()
②數(shù)組的比較
數(shù)組相等的條件是元素個(gè)數(shù)必須相等,并且對(duì)應(yīng)位置的元素也相等,這可以通過(guò)對(duì)每一個(gè)元素使用equals()比較
來(lái)判斷
③數(shù)組元素的比較
第一種是實(shí)現(xiàn)java.lang.Comparable接口,使你的類具有“天生”的比較能力,此接口比較簡(jiǎn)單,只有compareTo()
一個(gè)方法
第二種方式是創(chuàng)建一個(gè)實(shí)現(xiàn)了Comparator接口的單獨(dú)的類
④數(shù)組排序
Java標(biāo)準(zhǔn)類庫(kù)中的排序算法針對(duì)正排序的特殊類型進(jìn)行了優(yōu)化 -- 針對(duì)基本類型設(shè)計(jì)的“快速排序”以及針對(duì)對(duì)象
設(shè)計(jì)的“穩(wěn)定歸并排序”
⑤在已排序的數(shù)組中查找
如果數(shù)組已經(jīng)排好序了,就可以使用Arrays.binarySearch()執(zhí)行快速查找
第17章 容器深入研究
1.完整的容器分類法
包括了抽象類和遺留構(gòu)件
JavaSE5新添加了:
①Q(mào)ueue接口及其實(shí)現(xiàn)PriorityQueue和各種風(fēng)格的BlockingQueue
②ConcurrentMap接口及其實(shí)現(xiàn)ConcurrentHashMap,它們也是用于多線程機(jī)制的
③CopyOnWriteArrayList和CopyOnWriteArraySet,他們也是用于多線程機(jī)制的
④EnumSet和EnumMap,為使用enum而設(shè)計(jì)的Set和Map的特殊實(shí)現(xiàn)
⑤在Collection類中的多個(gè)便利方法
2.填充容器
兩種用對(duì)單個(gè)對(duì)象的引用來(lái)填充Collection的方式,第一種是使用Collection.nCopies()創(chuàng)建傳遞給構(gòu)造器的
List,這里填充的是ArrayList;第二種是使用Collection.fill()方法,但是它只能替換已經(jīng)在List中存在的
元素,而不能添加新的元素。
3.Collection的功能方法
包含add(T)、addAll(...)、clear()等。
注意:其中不包括隨機(jī)訪問(wèn)所選擇元素的get()方法。因?yàn)镃ollection包含Set,而Set是自己維護(hù)內(nèi)部順序的,要
想檢查Collection中的元素,就必須使用迭代器。
4.List的功能方法
基本的List很容易使用,大多數(shù)時(shí)候只是調(diào)用add()添加對(duì)象,使用get()一次取出一個(gè)元素,以及調(diào)用iterator()
獲取用于該序列的Iterator。
其他方法包括:basicTest()中包含每個(gè)List都可以執(zhí)行的操作;iteMotion()使用Iterator遍歷元素;對(duì)應(yīng)的
iterManipulation()使用Iterator修改元素;testVisual()用以查看List的操作效果等等。
5.Set和存儲(chǔ)順序
當(dāng)你創(chuàng)建自己的類型時(shí),要意識(shí)到Set需要一種方式來(lái)維護(hù)存儲(chǔ)順序,而存儲(chǔ)順序如何維護(hù),則是在Set的不同實(shí)現(xiàn)
之間會(huì)有所變化的。
①HashSet*
為快速查找而設(shè)計(jì)的Set,存入HashSet的元素必須定義hashCode()
②TreeSet
保持次序的Set,底層是樹(shù)結(jié)構(gòu)。使用它可以從Set中提取有序的序列,元素必須實(shí)現(xiàn)Comparable接口
③LinkedHashSet
具有HashSet的查詢速度,且內(nèi)部使用鏈表維護(hù)元素的順序(插入的順序)。于是在使用迭代器遍歷Set時(shí),結(jié)果
會(huì)按照元素插入的次序顯示。元素也必須定義hashCode()方法。
SortedSet:保證元素處于排序狀態(tài)。
6.隊(duì)列
除了并發(fā)應(yīng)用,Queue在Java中僅有的兩個(gè)實(shí)現(xiàn)是LinkedList和PriorityQueue,它們的差異在于排序行為而不是
性能。
7.理解Map
①性能
性能是映射表中一個(gè)重要問(wèn)題,當(dāng)在get()中使用線性搜索時(shí),執(zhí)行速度會(huì)相當(dāng)?shù)芈@正是HashMap提高速度的
地方。HashMap使用了特殊的值,稱作散列碼,來(lái)取代對(duì)鍵的緩慢搜索。散列碼是“相對(duì)唯一”的,用以代表對(duì)象
的int值,它是通過(guò)將該對(duì)象的某些信息進(jìn)行轉(zhuǎn)換而生成的。
②SortedMap
使用SortedMap可以確保鍵處于排序狀態(tài)。
③LinkedHashMap
為了提高速度,LinkedHashMap散列化所有的元素,但是在遍歷鍵值對(duì)時(shí),卻又以元素的插入順序返回鍵值對(duì)。
8.持有引用
SoftReference、WeakReference和PhantomReference由強(qiáng)到弱排列,對(duì)應(yīng)不同級(jí)別的“可獲得性”。
SoftReference用以實(shí)現(xiàn)內(nèi)存敏感的高速緩存。WeakReference是為實(shí)現(xiàn)“規(guī)范映射”而設(shè)計(jì)的,它不妨礙垃圾
回收器回收映射的“鍵”或“值”。PhantomReference用以調(diào)度回收前的清理工作,它比Java終止機(jī)制更靈活。