版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、Java編程思想學習筆記1面向?qū)ο蠛蚃VM基礎(chǔ) 1.java中的4種訪問制權(quán)限:(1).public:最大訪問控制權(quán)限,對所有的類都可見。(2).protect:同一包可見,不在同一個包的所有子類也可見。(3).default:包訪問權(quán)限,即同一個包中的類可以可見。默認不顯式指定訪問控制權(quán)限時就是default包訪問控制權(quán)限。(4).private:最嚴格俄訪問控制權(quán)限,僅該類本身可見,對外一切類都不可以訪問(反射機制可以訪問)。2.面向?qū)ο缶幊讨袃煞N對象組合方式is-a 和 has-a:(1).is-a組合:一個類繼承具有相似功能的另一個類,根據(jù)需要在所繼承的類基礎(chǔ)上進行擴展。優(yōu)點:具有共同
2、屬性和方法的類可以將共享信息抽象到父類中,增強代碼復(fù)用性,同時也是多態(tài)的基礎(chǔ)。缺點:子類中擴展的部分對父類不可見,另外如果共性比較少的時候使用繼承會增加冗余代碼。(2).has-a組合:has-a組合是在一個類中引用另一個類作為其成員變量。優(yōu)點:可擴展性和靈活性高。在對象組合關(guān)系中應(yīng)優(yōu)先考慮has-a組合關(guān)系。缺點:具有共性的類之間看不到派生關(guān)系。3.多態(tài):在面向?qū)ο缶幊讨校宇愔袚碛泻透割愊嗤椒ê灻姆椒ǚQ為子類方法覆蓋父類方法,當調(diào)用子類方法的某個操作時,不必明確知道子類的具體類型,只需要將子類類型看作是父類的引用調(diào)用其操作方法,在運行時,JVM會根據(jù)引用對象的具體子類類型而調(diào)用應(yīng)該的方
3、法,這就是多態(tài)。多態(tài)的基礎(chǔ)是java面向?qū)ο缶幊痰耐斫壎C制。編程中有如下兩種綁定機制:(1).早綁定:一般在非面向?qū)ο缶幊陶Z言中使用,在程序編譯時即計算出具體調(diào)用方法體的內(nèi)存地址。(2).晚綁定:面向?qū)ο缶幊陶Z言中經(jīng)常使用,在程序編譯時無法計算出具體調(diào)用方法體的內(nèi)存地址,只進行方法參數(shù)類型和返回值類型的校驗,在運行時才能確定具體要調(diào)用方法體的內(nèi)存地址。4.java單繼承的優(yōu)點:相比于C+的多繼承,java只支持類的單繼承,java中的所有類的共同基類是Object類,Object類java類樹的唯一根節(jié)點,這種單繼承有以下好處:(1).單繼承可以確保所有的對象擁有某種共同的特性,這樣對于JV
4、M虛擬機對所有的類進行系統(tǒng)級的操作將提供方便,所有的java對象可以方便地在內(nèi)存堆棧中創(chuàng)建,傳遞參數(shù)也變的更加方便簡單。(2).java的單繼承使得實現(xiàn)垃圾回收器功能更加容易,因為可以確保JVM知道所有對象的類型信息。5.選擇容器對象兩個原則:(1).容器所能提供不同的類型的接口和外部行為是否能夠滿足需求。(2).不同容器針對不同的操作效率不同。6.類型轉(zhuǎn)換:Java中有兩種常見的類型轉(zhuǎn)換:向上類型轉(zhuǎn)換(upcast)和向下類型轉(zhuǎn)換(downcast):(1).向上類型轉(zhuǎn)換(upcast):向上類型轉(zhuǎn)換是將子類對象強制類型轉(zhuǎn)換為父類類型,經(jīng)典用法是面向?qū)ο蟮亩鄳B(tài)特性。向上類型轉(zhuǎn)換時,子類對象的
5、特性將不可見,只有子類從父類繼承的特性仍然保持可見,向上類型轉(zhuǎn)換時編譯器會自動檢查是否類型兼容,通常是安全的。(2).向下類型轉(zhuǎn)換:向下類型轉(zhuǎn)換是將父類類型強制轉(zhuǎn)換為子類類型,轉(zhuǎn)換過后父類中不可見的子類特性又恢復(fù)可見性,向下類型轉(zhuǎn)換時,編譯器無法自動檢測是否類型兼容,往往會產(chǎn)生類型轉(zhuǎn)換錯誤的運行時異常,通常不安全。7.java中5個存放數(shù)據(jù)的地方:(1).寄存器(Registers):位于CPU內(nèi)部,是速度最快的存儲區(qū),但是數(shù)量和容量有限。在java中不能直接操作寄存器。(2).棧(Stack):棧位于通用隨機訪問存儲器 (General random-access memory,RAM,內(nèi)存
6、) 中,通過處理器的棧指針訪問,棧指針從棧頂向棧底分配內(nèi)存,從棧底向棧頂釋放內(nèi)存。棧是僅次于寄存器的速度第二快的存儲器,在java程序中,一般的8種 基本類型數(shù)據(jù)和對象的引用通常存放在棧內(nèi)存中,不通過new關(guān)鍵字的字符串對象也是存放在棧的字符串池中。棧的優(yōu)勢是,存取速度比堆要快,僅次于寄存器, 棧數(shù)據(jù)可以共享。但缺點是,存在棧中的數(shù)據(jù)大小與生存期必須是確定的,缺乏靈活性。(3).堆(Heap):也是位于通用隨機訪問存儲器 (General random-access memory,RAM,內(nèi)存) 中的共享內(nèi)存池。Java的堆是一個運行時數(shù)據(jù)區(qū),類的對象從中分配空間,凡是通過new關(guān)鍵字創(chuàng)建的對
7、象都存放在堆內(nèi)存中,它們不需要程序代碼來顯式的 釋放。堆是由垃圾回收來負責的,堆的優(yōu)勢是可以動態(tài)地分配內(nèi)存大小,生存期也不必事先告訴編譯器,因為它是在運行時動態(tài)分配內(nèi)存的,Java的垃圾收集器 會自動收走這些不再使用的數(shù)據(jù)。但缺點是,由于要在運行時動態(tài)分配內(nèi)存,存取速度較慢。(4).常量存儲器(Constant storage):java中的常量是存放在系統(tǒng)內(nèi)嵌的只讀存儲器中(read-only memory,ROM)的。(5).非隨機存儲器(Non-RAM storage):對于流對象和持久化對象,通常存放在程序外的存儲器,如硬盤。8.javadoc只處理public和protected訪問
8、控制權(quán)限的文檔注釋,private和default權(quán)限的穩(wěn)定注釋將被忽略。9.java中賦值運算:基本類型賦值是直接復(fù)制值,賦值操作后,相互不影響。引用類型賦值是復(fù)制引用值,相當于給對象取一個別名,賦值之后兩個引用指向同一個引用對象,相互之間有影響。在Java中,向方法傳遞引用類型參數(shù)會改變參數(shù)的值,不讓參數(shù)受到影響的解決方法:在方法內(nèi)首先先將引用克隆一份,然后操作克隆的對象。10.移位運算:左移運算符:將比特位右移指定位數(shù),如果是正數(shù),左邊第一位(符號位)補0,其余位補0,如果是負數(shù),左邊第一位補1,其余位補0。右移一位相當于除2。無符號右移運算符:將比特位右移指定位數(shù),不論是正數(shù)或者負數(shù),
9、左邊移除位統(tǒng)統(tǒng)補0。11.java中,比int類型小的原始類型(char、byte、short)進行數(shù)學運算或者位運算時,數(shù)據(jù)類型首先轉(zhuǎn)換成int類型,然后進行相應(yīng)的運算。12.方法重載(overloading):方法同名,參數(shù)列表不同稱為方法重載,注意方法的返回值類型不同不能作為方法重載。13.java中的析構(gòu)函數(shù):Java中沒有像C/C+的析構(gòu)函數(shù),用來銷毀不用的對象是否內(nèi)存空間,只有以下三個方法用于通知垃圾回收器回收對象。(1).finalize( )只是通知JVM的垃圾收集器當前的對象不再使用可以被回收了,但是垃圾回收器根據(jù)內(nèi)存使用狀況來決定是否回收。finalize()最有用的地方是
10、在JNI調(diào)用本地方法時(C/C+方法),調(diào)用本地方法的析構(gòu)函數(shù)消耗對象釋放函數(shù)。(2). System.gc()是強制析構(gòu),顯式通知垃圾回收器釋放內(nèi)存,但是垃圾回收器也不一定會立即執(zhí)行,垃圾回收器根據(jù)當前內(nèi)存使用狀況和對象的生命周期自行決定是否回收。(3).RunTime.getRunTime().gc()和System.gc()類似。注意:這三個函數(shù)都不能保證垃圾回收器立即執(zhí)行,推薦不要頻繁使用。14.垃圾回收器原理:(1).引用計數(shù)(ReferenceCounting)垃圾回收算法:一種簡單但是速度較慢的垃圾回收算法,每個對象擁有一個引用計數(shù)器(Reference Counter),當每次
11、引用附加到這個對象時,對象的引用計數(shù)器加1。當每次引用超出作用范圍或者被設(shè)置為null時,對象的引用計數(shù)器減1。垃圾回收 器遍歷整個對象列表,當發(fā)現(xiàn)一個對象的引用計數(shù)器為0時,將該對象移出內(nèi)存釋放。引用計數(shù)算法的缺點是,當對象環(huán)狀相互引用時,對象的引用計數(shù)器總不為0,要想回收這些對象需要額外的處理。引用計數(shù)算法只是用來解釋垃圾回收器的工作原理,沒有JVM使用它實現(xiàn)垃圾回收器。引用計數(shù)的改進算法:任何存活的對象必須被在靜態(tài)存儲區(qū)或者棧(Stack)中的引用所引用,因此當遍歷全部靜態(tài)存儲區(qū)或棧中的引用時,即可以確定所有存活的對象。每當 遍歷一個引用時,檢查該引用所指向的對象,同時檢查該對象上的所有
12、引用,沒有引用指向的對象和相互自引用的對象將被垃圾回收器回收。(2).暫停復(fù)制(stop-and-copy)算法:垃圾回收器的收集機制基于:任何一個存活的對象必須要被一個存儲在?;蛘哽o態(tài)存儲區(qū)的引用所引用。暫停復(fù)制的算法是:程序在運行過程中首先暫停執(zhí)行,把每個存活的對象從一個堆復(fù)制到另一個堆中,已經(jīng)不再被使用的對象被回收而不再復(fù)制。暫停復(fù)制算法有兩個問題:a.必須要同時維護分離的兩個堆,需要程序運行所需兩倍的內(nèi)存空間。JVM的解決辦法是在內(nèi)存塊中分配堆空間,復(fù)制時簡單地從一個內(nèi)存塊復(fù)制到另一個內(nèi)存塊。b.第二個問題是復(fù)制過程的本身處理,當程序運行穩(wěn)定以后,只會產(chǎn)生很少的垃圾對象需要回收,如果垃
13、圾回收器還是頻繁地復(fù)制存活對象是非常低性能的。JVM的解決方法是使用一種新的垃圾回收算法標記清除(mark-and-sweep)。一般來說標記清除算法在正常的使用場景中速度比較慢,但是當程序只產(chǎn)生很少的垃圾對象需要回收時,該算法就非常的高效。(3).標記清除(mark-and-sweep)算法:和暫停復(fù)制的邏輯類似,標記清除算法從棧和靜態(tài)存儲區(qū)開始追蹤所有引用尋找存活的對象,當每次找到一個存活的對象時,對象被設(shè)置一個標記并且不被回收,當標記過程完成后,清除不用的死對象,釋放內(nèi)存空間。標記清除算法不需要復(fù)制對象,所有的標記和清除工作在一個內(nèi)存堆中完成。注意:SUN的文檔中說JVM的垃圾回收器是一
14、個后臺運行的低優(yōu)先級進程,但是在早期版本的JVM中并不是這樣實現(xiàn)的,當內(nèi)存不夠用時,垃圾回收器先暫停程序運行,然后進行垃圾回收。(4).分代復(fù)制(generation-copy)算法:一種對暫停復(fù)制算法的改進,JVM分配內(nèi)存是按塊分配的,當創(chuàng)建一個大對象時,需要占用一塊內(nèi)存空間,嚴格的暫停復(fù)制算法在釋放老內(nèi)存堆之前要求把每個存活的對象從源堆拷貝到新堆,這樣做非常的消耗內(nèi)存。通過內(nèi)存堆,垃圾回收器可以將對象拷貝到回收對象的內(nèi)存堆中,每個內(nèi)存塊擁有一個世代計數(shù)(generation count)用于標記對象是否存活。每個內(nèi)存塊通過對象被引用獲得世代計數(shù),一般情況下只有當最老的內(nèi)存塊被回收時才會創(chuàng)建
15、新的內(nèi)存塊,這主要用于處理大 量的短存活周期臨時對象回收問題。一次完整的清理過程中,內(nèi)存塊中的大對象不會被復(fù)制,只是根據(jù)引用重新獲得世代計數(shù)。JVM監(jiān)控垃圾回收器的效率,當發(fā)現(xiàn)所有的對象都是長時間存活時,JVM將垃圾回收器的收集算法調(diào)整為標記清除,當內(nèi)存堆變得零散碎片時,JVM又重新將垃圾回收器的算法切換會暫停復(fù)制,這就是JVM的自適應(yīng)分代暫停復(fù)制標記清除垃圾回收算法的思想。15.java即時編譯技術(shù)(JIT):Java的JIT是just-in-timecomplier技術(shù),JIT技術(shù)是java代碼部分地或全部轉(zhuǎn)換成本地機器碼程序,不再需要JVM解釋,執(zhí)行速度更快。當一個”.class”的類文
16、件被找到時,類文件的字節(jié)碼被調(diào)入內(nèi)存中,這時JIT編譯器編譯字節(jié)碼代碼。JIT有兩個不足:(1).JIT編譯轉(zhuǎn)換需要花費一些時間,這些時間貫穿于程序的整個生命周期。(2).JIT增加了可執(zhí)行代碼的size,相比于壓縮的字節(jié)碼,JIT代碼擴展了代碼的size,這有可能引起內(nèi)存分頁,進而降低程序執(zhí)行速度。對JIT不足的一種改進技術(shù)是延遲評估(lazy evaluation):其基本原理是字節(jié)碼并不立即進行JIT編譯除非必要,在最近的JDK中采用了一種類似延遲JIT的HotSpot方法對每次執(zhí)行的代碼進行優(yōu)化,代碼執(zhí)行次數(shù)越多,速度越快。16.非內(nèi)部類的訪問控制權(quán)限只能是默認的包訪問權(quán)限或者是pub
17、lic的,不能是protected和private的。內(nèi)部類的訪問控制權(quán)限可以是protected和private。17.Java中的高精度數(shù)值類型:BigInteger和BigDecimal是java中的高精度數(shù)值類型,由于它們是用于包裝java的基本數(shù)據(jù)類型,因此這兩個高精度數(shù)值類型沒有對應(yīng)的原始類型。(1).BigInteger支持任意精度的整數(shù),即使用BigInteger可以表示任意長度的整數(shù)值而在運算中不會因為范圍溢出丟失信息。(2).BigDecimal支持任意精度的固定位數(shù)浮點數(shù),可以用來精確計算貨幣等數(shù)值。普通的float和double型浮點數(shù)因為受到小數(shù)點位數(shù)限制,在運算時不
18、能準確比較,只能以誤差范圍確定是否相等,而BigDecimal就可以支持固定位數(shù)的浮點數(shù)并進行精確計算。18.Java只處理public和protected訪問控制權(quán)限成員的文檔注釋,private和默認的包訪問控制權(quán)限成員的文檔注釋將被忽略。19.Java中賦值運算:Java中賦值運算是把賦值運算符”=”右邊的值簡稱右值拷貝到賦值運算符左邊的變量,如a=b,即把b代表的變量或常量值復(fù)制給變量a,切記a只能是變量,不能說常量值。(1).原始類型賦值運算:Java中8種原始數(shù)據(jù)類型賦值運算是將賦值運算符右邊的值拷貝到賦值運算符左邊的變量中。原始類型賦值運算后,無論改變賦值運算符那一邊的值,都不會
19、影響賦值運算符另一邊的值。(2).引用類型的賦值運算:Java中除了8中原始數(shù)據(jù)類型外,所有的數(shù)據(jù)類型都是對象類型,對象類型的賦值運算是操作引用,如a=b,把b引用賦值給a引用,即原本b引用指向的對象現(xiàn)在由a和b引用同時指向。引用賦值運算符又叫別名運算符,即它相當于給引用對象取了一個別名,其實引用的還是同一個對象。引用類型的賦值運算,如果賦值運算符任意一邊的引用改變了被引用對象的值,賦值運算符另一邊的引用也會受影響,因為兩個引用指向的是同一個被引用的對象。2對象初始化和面向?qū)ο筇匦?1.java類的初始化順序:(1).在一個類中,初始化順序由變量在類中的聲明定義順序決定,成員變量(非set方法
20、和構(gòu)造方法的初始化)的初始化發(fā)生在方法調(diào)用之前,包括構(gòu)造方法。(2).靜態(tài)變量在整個存儲區(qū)只保留一份拷貝,本地變量不能使用靜態(tài)關(guān)鍵字,基本類型的靜態(tài)變量不需要初始化,它會根據(jù)類型獲得初始化值,引用類型的靜態(tài)變量默認初始化為null。靜態(tài)變量的初始化發(fā)送在需要使用的時候,一旦被初始化之后,靜態(tài)變量就不會再初始化。(3).靜態(tài)初始化塊和靜態(tài)變量類似的執(zhí)行也在構(gòu)造方法之前,并且僅執(zhí)行一次。(4).動態(tài)初始化塊(與靜態(tài)初始化塊類似,只是沒有static關(guān)鍵字,即放在一對大括號中的代碼塊)在靜態(tài)初始化塊初始化結(jié)束后執(zhí)行,動態(tài)初始化塊每次創(chuàng)建新對象都會初始化一次。(5).構(gòu)造方法執(zhí)行時,先執(zhí)行父類的構(gòu)造方
21、法,后執(zhí)行子類的構(gòu)造方法。(6).本地變量初始化最晚,在方法中初始化。綜述,類的初始化順序依次為:a.父類的靜態(tài)變量/靜態(tài)初始化塊;b.子類類的靜態(tài)變量/靜態(tài)初始化塊;c.父類的動態(tài)初始化塊、非構(gòu)造方法和set方法的成員變量初始化d.子類的動態(tài)初始化塊、非構(gòu)造方法和set方法的成員變量初始化e.父類的構(gòu)造方法。f.子類的構(gòu)造方法。g.父類本地變量。h.子類的本地變量。2.數(shù)組初始化:Java中數(shù)組初始化有以下3中方式:(1).數(shù)組聲明時直接初始化,如:int a = 1,2,3;(2).動態(tài)數(shù)組初始化,如:int a = new int1,2,3;注意:動態(tài)數(shù)組初始化時,不能在new()操作符
22、中指定數(shù)組的大小,即int a = new int31,2,3的寫法是錯誤的,數(shù)組的大小由初始化數(shù)組元素個數(shù)決定。(3).固定長度數(shù)組初始化,如:int a = new int3;a1 = 0;a2 = 1;a3 = 2;注意:固定長度大小的數(shù)組初始化時不能大于所聲明的數(shù)組長度,沒有聲明的數(shù)組元素使用其默認值,如int默認為0,對象類型的值為引用,默認為null.3.java代碼重用4中方式:java面向?qū)ο缶幊讨刑峁┝巳缦?中代碼重用的方式:(1).組合:面向?qū)ο缶幊讨凶畛S玫拇a復(fù)用方式,具體的方式是在一個對象中將另一個對象引用最為成員變量,其最大的優(yōu)點是既實現(xiàn)松散耦合,有可能提高代碼復(fù)用
23、率。(2).繼承:面向?qū)ο缶幊讨谐S玫奶岣叽a復(fù)用率的方法之一,適用于子類和父類是同一種抽象類型,具有共同的屬性情況。使用繼承,子類可以復(fù)用父類除private私有房屋控制權(quán)限以為的所有屬性和方法,編譯器將父類封裝為子類對象內(nèi)部的一個對象。需要注意的是:調(diào)用子類初始化構(gòu)造方法時,編譯器會確保首先調(diào)用父類的構(gòu)造方法初始化父類,然后才初始化子類,如果父類中沒有默認的構(gòu)造方法,即需要顯式傳入?yún)?shù)的構(gòu)造方法時,子類必須通過super關(guān)鍵字顯式傳入?yún)?shù)調(diào)用父類的構(gòu)造方法。(3).委派:Java中不支持委派方式的代碼復(fù)用,但是開發(fā)人員可以使用委派機制實現(xiàn)代碼的重用。委派是指,java對象的所有方法其實都是
24、委派調(diào)用另一個類的方法實現(xiàn),但是當前類又不是所委派類的類型,因此使用繼承不太合適,解決方式和組合類似,將被委派類作為委派類的成員變量,委派類的方法直接調(diào)用被委派類對象應(yīng)用的方法。如:javaview plaincopy1. /委派類2. publicClassA3. /被委派類4. privateBb=newClassB();5. publicvoidmethod1()6. b.method1();7. 8. publicvoidmethod2()9. b.method2();10. 11. 12. (4).聯(lián)合使用組合和繼承方式:因為java中不允許多繼承,如果某種情況下,一個java類需要
25、使用多個其他類功能,且該類和其中某個類具有很多共同屬性,即可以看作同一類,則可以使當前類繼承具體共同屬性的類,同時將其他類作為成員變量組合引用。4.組合和繼承的區(qū)別:組合和繼承都可以復(fù)用代碼,很多java程序員,甚至是架構(gòu)師都分不清楚什么情況下該使用組合,什么情況下應(yīng)該使用繼承,具體的區(qū)別如下:(1).組合:組合通常是在一個類中想使用另一個類已有的特性,但是卻不想使用其接口。使用組合可以可以將一個類作為當前類的內(nèi)嵌對象,這樣在當前類中就可以顯式地使用內(nèi)嵌類已經(jīng)實現(xiàn)的功能,與此同時又不會影響當前類的調(diào)用接口。(2).繼承:繼承是隱式地使用被繼承類的功能,相當于提供了一個新版本的父類實現(xiàn)。使用繼承
26、,子類不但可以復(fù)用父類的功能,同時還復(fù)用了父類的接口,子類和父類的對外調(diào)用接口相同的情況下適合使用繼承。使用繼承時,很多情況下需要向上類型轉(zhuǎn)換,即將子類看作其父類。在編程時到底選用組合方式還是繼承方式,一個簡單的判斷依據(jù)是:是否需要向上類型轉(zhuǎn)換,如果需要就使用繼承,如果不需要,則選擇組合。5.final方法:Java中使用final類型的方法有以下兩種原因:(1).設(shè)計原因:final類型的方法不允許其子類修改方法,即不允許子類覆蓋父類的final方法。(2).效率原因:在早期的java實現(xiàn)中,如果方法被聲明為final,編譯器將final方法調(diào)用編譯為內(nèi)聯(lián)調(diào)用。正常的方法調(diào)用是:如果方法調(diào)用
27、時,將當前的方法上下文保持到棧中,調(diào)用被調(diào)用的方法,然后在將調(diào)用上下文出棧恢復(fù)調(diào)用現(xiàn)場。內(nèi)聯(lián)調(diào)用是:如果方法調(diào)用時,將被調(diào)用方法體拷貝到當前調(diào)用的地方合并成一個方法體,這樣就避免因需要保存方法調(diào)用線程而進行的進棧和出棧操作,可以提高效率。新版的使用hotspot技術(shù)的java虛擬機可以探測方法調(diào)用情況而做效率優(yōu)化,final方法不再作為提高效率的手段,唯一的作用是確保方法不被子類覆蓋。注意:任何private的方法都是隱式的final類型,同final方法類似,private方法不能被子類所覆蓋,但是private比final更嚴格,基類的private方法對子類不可見,private方法不再
28、是接口的一部分。6.多態(tài)性:面向?qū)ο缶幊讨械亩鄳B(tài)和繼承往往是一起發(fā)揮作用的,使用繼承,所有的子類和父類使用相同的對外接口,而多態(tài)的基礎(chǔ)是晚綁定或動態(tài)綁定或運行時綁定, 即對象引用使用基類類型,在編譯時編譯器無法確切知道到底調(diào)用哪一個具體類,只有在運行時,java虛擬機才通過類型檢查確定調(diào)用對象的具體類型。Java中默認對象引用全部是晚綁定,只有static和final類型的引用時早綁定或編譯時綁定。多態(tài)的優(yōu)勢是:程序的可擴張性好,無論添加多少個子類,基類的接口都不用改變,只需要在子類對應(yīng)方法中提供具體實現(xiàn)即可,也就是所謂的將程序變化的部分和程序保持不變的部分分離。注意:只有正常的方法可以使用多
29、態(tài),字段和靜態(tài)方法沒有多態(tài)機制。 構(gòu)造方法也不支持多態(tài)機制,構(gòu)造方法是隱式的static聲明。3內(nèi)部類 1.java中,可以將一個類的定義放在另一個類的內(nèi)部,這種叫做內(nèi)部類。內(nèi)部類允許編程人員將邏輯上相關(guān)的類組織在一起,并且控制內(nèi)部類對其他類的可見性。2.在外部類的非靜態(tài)方法中創(chuàng)建內(nèi)部類的對象語法:外部類類名.內(nèi)部類類名 對象名 = 外部類對象.new 內(nèi)部類類名();如:javaview plaincopy1. publicclassOutter2. classinner3. 4. 5. Outterout=newOutter();6. Outter.Innerinner=out.newIn
30、ner();注意:非靜態(tài)的內(nèi)部類必須要有外部類對象之后才能創(chuàng)建,因為外部類對象持有內(nèi)部類的引用,如果內(nèi)部類是靜態(tài)的,則不需要外部類對象引用內(nèi)部類對象。3.內(nèi)部類對外部類對象的引用:外部類中所有的元素對內(nèi)部類都是可見的,內(nèi)部類持有對外部類對象引用的語法:外部類名稱.this。如:javaview plaincopy1. publicclassOutter2. voidf()3. System.out.println(“Outterf()method”);4. 5. classInner6. publicOutterouter()7. returnOutter.this;8. 9. 10. pub
31、licInnerinner()11. returnnewInner();12. 13. 4.方法內(nèi)部類:除了最常見的最為成員變量的內(nèi)部類以外,內(nèi)部類還可以定義在方法中,如:javaview plaincopy1. publicclassOutter2. publicInnergetInner()3. classInner4. publicvoidf()5. System.out.println(“Methodinnerclass”);6. 7. 8. returnnewInner();9. 10. publicvoidfout()11. Innerinner=getInner();12. in
32、ner.f();13. 14. 5.匿名內(nèi)部類:Java中匿名內(nèi)部類的應(yīng)用十分廣泛,所謂的匿名內(nèi)部類就是指所創(chuàng)建的內(nèi)部類沒有類名稱,也就是不知道內(nèi)部類的具體類型,如:javaview plaincopy1. publicclassOutter2. publicInnergetInner()3. returnnewInner()4. privateStringname=“inner”;5. publicStringgetName()6. returnname;7. 8. ;9. 10. 上面的return newInner;就是一個匿名內(nèi)部類,這個匿名內(nèi)部類繼承了Inner類,即其基類是Inne
33、r,但是其具體類型不清楚,該匿名內(nèi)部類等效于下面的內(nèi)部類寫法:javaview plaincopy1. publicclassOutter2. classMyInnerimplementInner3. privateStringname=“Innerclass”;4. publicStringgetName()5. returnname;6. 7. 8. publicInnergetInner()9. returnnewMyInner();10. 11. 注意:匿名內(nèi)部類是實現(xiàn)了new關(guān)鍵字之后的接口或繼承了類,只是沒有具體的類名稱。6.內(nèi)名內(nèi)部類傳遞final參數(shù):如果在創(chuàng)建匿名內(nèi)部類,需要
34、外部類傳遞參數(shù)時,參數(shù)必須是final類型的,否則,編譯時會報錯。如:javaview plaincopy1. publicclassOutter2. publicInnergetInner(finalStringname)3. returnnewInner()4. publicnamegetName()5. returnname;6. 7. ;8. 9. 注意:如果外部類傳遞的參數(shù)在內(nèi)部類中使用,則必須是final類型,如果沒有在內(nèi)部類中使用(如,僅在基類中使用),則可以不用是final類型的。7.靜態(tài)內(nèi)部類:靜態(tài)內(nèi)部類又稱為嵌套類,靜態(tài)內(nèi)部類和普通內(nèi)部類的區(qū)別:(1).對于非靜態(tài)的內(nèi)部類來
35、說,內(nèi)部類和外部類必須保持對象引用,內(nèi)部類可以訪問外部類的任何元素.(2).靜態(tài)內(nèi)部類不需要和外部類保持對象引用,靜態(tài)內(nèi)部類只能訪問外部類的靜態(tài)元素。8.為什么要使用內(nèi)部類:使用內(nèi)部類主要有以下兩個原因:(1).解決java中類不能多繼承的問題:Java中的繼承是單繼承,在某些情況下接口的多繼承可以解決大部分類似C+中多繼承的問題,但是如果一個類需要繼承兩個父類而不是接口,在java中是沒法實現(xiàn)這種功能的,內(nèi)部類可以幫助我們部分解決這種問題,如:javaview plaincopy1. abrstactclassA2. abstractpublicvoidf();3. 4. abstractc
36、lassB5. abstractpublicvoidg();6. 7. publicclassDextendsA8. publicvoidf()9. publicBmakeB()10. returnnewB()11. publicvoidg();12. 13. 14. 這樣既繼承了A類,有在makeB方法中使用匿名內(nèi)部類繼承了B類。(2).閉包方法問題:在面向?qū)ο笾杏袀€術(shù)語叫閉包,所謂閉包是指一個可調(diào)用的對象,它記錄了一些信息,這些信息來自于創(chuàng)建它的作用域。Java中不支持閉包,但是 java的內(nèi)部類可以看作是對閉包的一種解決方案,因為外部類的所有元素對于普通的內(nèi)部類來說都是可見的,并且內(nèi)部類
37、還包含一個指向外部類的對象引用,因 此在作用域內(nèi),內(nèi)部類有權(quán)操作外部類的所有成員包括private成員。如:javaview plaincopy1. interfaceIncrementable2. voidincrement();3. 4. 5. classCallee1implementsIncrementable6. privateinti=0;7. publicvoidincrement()8. i+;9. System.out.println(i);10. 11. 12. 13. classMyIncrement14. voidincrement()15. System.out.pr
38、intln(otherincrement);16. 17. staticvoidf(MyIncrementmi)18. mi.increment();19. 20. 21. 22. classCallee2extendsMyIncrement23. privateinti=0;24. privatevoidincr()25. i+;26. System.out.println(i);27. 28. /閉包內(nèi)部類29. privateclassClosureimplementsIncrementable30. publicvoidincrement()31. incr();32. 33. 34.
39、 /回調(diào)函數(shù)35. IncrementablegetCallbackReference()36. /新建內(nèi)部類37. returnnewClosure();38. 39. 40. 41. classCaller42. privateIncrementablecallbackRefference;43. Caller(Incrementablecbh)44. callbackRefference=cbh;45. 46. voidgo()47. /調(diào)用increment()方法48. callbackRefference.increment();49. 50. 51. 52. publicclas
40、sCallbacks53. publicstaticvoidmain(Stringargs)54. Callee1c1=newCallee1();55. Callee2c2=newCallee2();56. MyIncrement.f(c2);57. Callercaller1=newCaller(c1);58. /將內(nèi)部類中的Closure賦給Caller59. Callercaller2=newCaller(c2.getCallbackReference();60. caller1.go();61. caller1.go();62. caller2.go();63. caller2.go(
41、);64. 65. 66. 67. 68. 輸出:69. otherincrement70. 171. 272. 173. 274. Callee2通過使用內(nèi)名內(nèi)部類提供了一個訪問自身increment方法的鉤子,通過getCallbackReference()方法獲取內(nèi)部類對象的引用,進而通 過內(nèi)部類的increment方法調(diào)用外部類的回調(diào)方法,這就是java中用于實現(xiàn)回調(diào)方法的閉包。75. 4集合容器 1.集合中添加另一個集合的方法:(1).Collection.addAll(被添加的Collection對象)方法:如:list1.addAll(list2);(2).Collections
42、.addAll(添加到的目標Collection對象,可變參數(shù)的集合或者對象)方法:如:Collections.addAll(list1, new Object1(), new Object2(); Collectionns.addAll(list1, list2);注意:Collections是java集合容器的工具類,相比于(1),使用Collections的(2)更靈活。2.Java集合中常用的交集、并集和差集操作:并集:collection對象1.addAll(collection對象2);交集:collection對象1. retainAll(collection對象2);差集:co
43、llection對象1. removeAll(collection對象2);注意:上述的集合操作時,集合元素的equals方法會影響操作結(jié)果。3.將其他類型集合轉(zhuǎn)換為List:Arrays.asList(非List類型的集合對象/可變參數(shù)的對象);方法可以將傳遞的參數(shù)轉(zhuǎn)變?yōu)長ist集合。如:Arrays.asList(new Object1(),new Object2(),);Arrays和Collections類似,是Array數(shù)組類型集合的工具類。注意:Arrays.asList()方法轉(zhuǎn)換后的List對象是一個size不能改變的對象,如果對該對象做增加或者刪除元素操作時,將會報不支持的操
44、作異常。4.List集合:List集合主要有兩種具體的集合容器:ArrayList和LinkedList。(1).ArrayList:底層實現(xiàn)是數(shù)組,提供了根據(jù)數(shù)組下標快速隨機訪問的能力,但是增加和刪除元素時因為需要引動數(shù)組的元素,因此比較慢。(2).LinkedList:底層實現(xiàn)是鏈表,鏈表訪問元素時必須從鏈表頭至鏈表尾挨個查找,因此只能順序訪問,速度比隨機訪問要慢。但是增加和刪除元素時,只需要修改鏈表的指針而不需要移動元素,因此速度比較快。5.LinkedList:LinkedList除了實現(xiàn)了基本的List接口以外,還提供了一些特定的方法,使得LinkedList可以方便地實現(xiàn)Stack
45、、Queue以及雙端Queue的功能。LinkedList提供的非List接口方法:(1).getFirst():獲取并且不移除LinkedList集合中第一個元素。如果集合為空,拋出NoSuchElementException異常。(2).element():獲取并且不移除LinkedList集合中第一個元素。如果集合為空,拋出NoSuchElementException異常。(3).peek():獲取并且不移除LinkedList集合中第一個元素。如果集合為空,則返回null。(4).removeFirst():獲取并且移除LinkedList集合中第一個元素。如果集合為空,拋出NoSuc
46、hElementException異常。(5).remove():獲取并且移除LinkedList集合中第一個元素。如果集合為空,拋出NoSuchElementException異常。(6).poll():獲取并且移除LinkedList集合中第一個元素。如果集合為空,則返回null。(7).addFirst():向LinkedList集合的頭部插入一個元素。(8).add():向LinkedList集合的尾部插入一個元素。(9).offer():向LinkedList集合的尾部插入一個元素。(10).removeLast():獲取并且移除LinkedList集合中最后一個元素。如果集合為空,
47、拋出NoSuchElementException異常。6.Iterator:Iterator迭代器在java集合容器中應(yīng)用比較廣泛,對于List類型的集合,可以通過下標索引值獲取到指定的元素,而對于Set類型的集合,因為Set是沒有索引的,因此只能通過迭代器來遍歷。Iterator迭代器是一個順序選擇和遍歷集合元素的對象,使用者不需要關(guān)心其底層的數(shù)據(jù)結(jié)構(gòu)和實現(xiàn)方式。Java中的Iterator迭代器是單向的。Iterator的常用方法如下:(1).collection對象.iterator()方法:將集合對象轉(zhuǎn)換為Iterator迭代器。(2).iterator對象.hasNext()方法:判
48、斷迭代器中是否還有元素。(3).iterator對象.next()方法:獲取迭代器中下一個元素。(4).iterator對象.remove()方法:刪除迭代器中當前元素。注意:使用迭代器的好處是,當數(shù)據(jù)結(jié)構(gòu)從List變?yōu)镾et之后,迭代集合的相關(guān)代碼一點都不用改變。7.ListIterator:ListIterator是Iterator的子類,它只能有List類型的集合產(chǎn)生,ListIterator是一個雙向的迭代器,即它可以向前和向后雙向遍歷集合。ListIterator的常用方法如下:(1).list類型對象.listIterator():將List類型的集合轉(zhuǎn)換為ListIterator
49、迭代器。(2).list類型對象.listIterator(int n):將List類型的集合轉(zhuǎn)換為ListIterator迭代器,同時指定迭代器的起始元素為第n個元素。(3).listIterator對象.hasNext():判斷迭代器中是否還有下一個元素。(4).listIterator對象.next():獲取迭代器中的下一個元素。(5).listIterator對象.hasPrevious():判斷迭代器中是否還有前一個元素。(6).listIterator對象.previous():獲取迭代器中的前一個元素。(7).listIterator對象.set(元素對象):將當前迭代到的元素設(shè)
50、置為另一個值。8.Map遍歷3中方法:Mapmap = new HashMap();map.put(“test1”, object1);map.put(“testn” , objectn);(1).Map的values()方法可以獲取Map值的集合:javaview plaincopy1. Iteratorit=map.values().iterator();2. while(it.hasNext()3. Objectobj=it.next();4. (2).Map的keySet方法可以獲取Map鍵的Set集合:javaview plaincopy1. Setkeys=map.keySet()
51、;2. for(Iteratorit=key.iterator();it.hasNext();)3. Stringkey=it.next();4. Objectobj=map.get(key);5. (3).通過使用Entry來得到Map的key和value:javaview plaincopy1. SetMap.EntryentrySet=map.entrySet();2. for(IteratorMap.Entryit=entrySet.iterator();it.hasNext();)3. Map.Entryentry=it.next();4. Stringkey=entry.getKey();5. Objectvalue=entry.getValue();6. 9.Collection和Iterator:Collection是java中除了Map以外的集合容器的通用接口,如果想自定義一種集合容器類型的類,可以選擇實現(xiàn)Collection接口或者繼承Collection的子類。實現(xiàn)Collection接口或者繼承Collection子類的時候,必須實現(xiàn)Collection接口的所有方法,而Iterator為定義自 定義集合容器類型提供了另一種方便,Iterator是一種輕量級的接口,只需要實現(xiàn)has
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年汽車銷售合同擔保服務(wù)模板附車輛改裝服務(wù)3篇
- 2024年短期公租房租賃合同
- 崗位職責表課程設(shè)計
- 2024幼兒園發(fā)展規(guī)劃(35篇)
- 基于機器學習的古代繪畫修復(fù)與復(fù)原技術(shù)研究
- 2024年營銷工作計劃(59篇)
- 沼氣池儲氣罐課程設(shè)計
- 線描西蘭花課程設(shè)計
- 英漢互譯系統(tǒng)的課程設(shè)計
- 物流行業(yè)運輸司機工作總結(jié)
- 公務(wù)員調(diào)任(轉(zhuǎn)任)審批表 - 陽春人才網(wǎng)
- IE部成立工作規(guī)劃
- 單體調(diào)試及試運方案
- 2023-2024學年浙江省杭州市城區(qū)數(shù)學四年級第一學期期末學業(yè)水平測試試題含答案
- 網(wǎng)球技術(shù)與戰(zhàn)術(shù)-華東師范大學中國大學mooc課后章節(jié)答案期末考試題庫2023年
- 2023年35kV集電線路直埋施工方案
- 思政教師培訓(xùn)心得體會2021
- HLB值的實驗測定方法
- 2023年《病歷書寫基本規(guī)范》年度版
- 防止電力生產(chǎn)事故的-二十五項重點要求2023版
- 代理記賬機構(gòu)代理記賬業(yè)務(wù)規(guī)范
評論
0/150
提交評論