Java編程思想小結(jié)

第一章 對(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ī)制更靈活。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,778評(píng)論 18 399
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,991評(píng)論 19 139
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說(shuō)閱讀 11,184評(píng)論 6 13
  • (一)Java部分 1、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,143評(píng)論 0 62
  • 日子一天天過(guò)去,但是任務(wù)量沒(méi)完成多少。 要加油啊,不能落下。 時(shí)間就這么多,要提高效率啊。 事情已經(jīng)很多,要分清主...
    良辰美LiangChen閱讀 83評(píng)論 0 0